<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>Node 第 6 天 | Megasu的笔记</title>
    <meta name="generator" content="VuePress 1.5.4">
    <link rel="icon" href="/heima2020/favicon.ico">
    <meta name="description" content="Megasu的笔记整理">
    <meta name="author" content="Megasu">
    <meta name="Keywords" content="学习网站,前端,分享">
    <link rel="preload" href="/heima2020/assets/css/0.styles.aa663799.css" as="style"><link rel="preload" href="/heima2020/assets/js/app.e2adc9d2.js" as="script"><link rel="preload" href="/heima2020/assets/js/2.7389c9d3.js" as="script"><link rel="preload" href="/heima2020/assets/js/7.f611fe3c.js" as="script"><link rel="prefetch" href="/heima2020/assets/js/10.8b750e5f.js"><link rel="prefetch" href="/heima2020/assets/js/11.9224f975.js"><link rel="prefetch" href="/heima2020/assets/js/12.3ea117b6.js"><link rel="prefetch" href="/heima2020/assets/js/13.7524b74f.js"><link rel="prefetch" href="/heima2020/assets/js/14.cee0fcf8.js"><link rel="prefetch" href="/heima2020/assets/js/15.7a4a27f7.js"><link rel="prefetch" href="/heima2020/assets/js/16.947d882b.js"><link rel="prefetch" href="/heima2020/assets/js/17.79d3becb.js"><link rel="prefetch" href="/heima2020/assets/js/18.48208e3a.js"><link rel="prefetch" href="/heima2020/assets/js/19.3d0c49ef.js"><link rel="prefetch" href="/heima2020/assets/js/20.1f6114c8.js"><link rel="prefetch" href="/heima2020/assets/js/21.85e67b4a.js"><link rel="prefetch" href="/heima2020/assets/js/22.ce482f4d.js"><link rel="prefetch" href="/heima2020/assets/js/23.a150bd35.js"><link rel="prefetch" href="/heima2020/assets/js/24.8cd80d5d.js"><link rel="prefetch" href="/heima2020/assets/js/25.0001c7c1.js"><link rel="prefetch" href="/heima2020/assets/js/26.aa4d65a5.js"><link rel="prefetch" href="/heima2020/assets/js/27.baffff1d.js"><link rel="prefetch" href="/heima2020/assets/js/28.20430dcf.js"><link rel="prefetch" href="/heima2020/assets/js/29.7bbc3c04.js"><link rel="prefetch" href="/heima2020/assets/js/3.0076a912.js"><link rel="prefetch" href="/heima2020/assets/js/30.5f74696f.js"><link rel="prefetch" href="/heima2020/assets/js/31.a0bf56d6.js"><link rel="prefetch" href="/heima2020/assets/js/32.dd5a93dd.js"><link rel="prefetch" href="/heima2020/assets/js/33.92de7335.js"><link rel="prefetch" href="/heima2020/assets/js/34.bf468ed6.js"><link rel="prefetch" href="/heima2020/assets/js/35.28502be1.js"><link rel="prefetch" href="/heima2020/assets/js/36.3622a14c.js"><link rel="prefetch" href="/heima2020/assets/js/37.626e17d3.js"><link rel="prefetch" href="/heima2020/assets/js/38.860020b8.js"><link rel="prefetch" href="/heima2020/assets/js/39.c092c283.js"><link rel="prefetch" href="/heima2020/assets/js/4.586af112.js"><link rel="prefetch" href="/heima2020/assets/js/40.a6ba2743.js"><link rel="prefetch" href="/heima2020/assets/js/41.43d70bcd.js"><link rel="prefetch" href="/heima2020/assets/js/42.6486a709.js"><link rel="prefetch" href="/heima2020/assets/js/43.670b256a.js"><link rel="prefetch" href="/heima2020/assets/js/44.eb371480.js"><link rel="prefetch" href="/heima2020/assets/js/45.5b45f11e.js"><link rel="prefetch" href="/heima2020/assets/js/46.bc59be94.js"><link rel="prefetch" href="/heima2020/assets/js/47.ec36fca9.js"><link rel="prefetch" href="/heima2020/assets/js/48.51e80f8f.js"><link rel="prefetch" href="/heima2020/assets/js/5.6eb7e243.js"><link rel="prefetch" href="/heima2020/assets/js/6.1b7d5a6d.js"><link rel="prefetch" href="/heima2020/assets/js/8.c14cc922.js"><link rel="prefetch" href="/heima2020/assets/js/9.cd5538bb.js">
    <link rel="stylesheet" href="/heima2020/assets/css/0.styles.aa663799.css">
  </head>
  <body>
    <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/heima2020/" class="home-link router-link-active"><!----> <span class="site-name">Megasu的笔记</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/heima2020/" class="nav-link">
  首页
</a></div> <!----></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/heima2020/" class="nav-link">
  首页
</a></div> <!----></nav>  <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><a href="/heima2020/node/day01" class="sidebar-heading clickable open"><span>Node</span> <!----></a> <ul class="sidebar-links sidebar-group-items"><li><a href="/heima2020/node/day01.html" class="sidebar-link">Node 第 1 天</a></li><li><a href="/heima2020/node/day02.html" class="sidebar-link">Node 第 2 天</a></li><li><a href="/heima2020/node/day03.html" class="sidebar-link">Node 第 3 天</a></li><li><a href="/heima2020/node/day04.html" class="sidebar-link">Node 第 4 天</a></li><li><a href="/heima2020/node/day05.html" class="sidebar-link">Node 第 5 天</a></li><li><a href="/heima2020/node/day06.html" aria-current="page" class="active sidebar-link">Node 第 6 天</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/heima2020/node/day06.html#node-第-6-天" class="sidebar-link">Node 第 6 天</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/heima2020/node/day06.html#_1-学习目标" class="sidebar-link">1.  学习目标</a></li><li class="sidebar-sub-header"><a href="/heima2020/node/day06.html#_2-web-开发模式" class="sidebar-link">2.  web 开发模式</a></li><li class="sidebar-sub-header"><a href="/heima2020/node/day06.html#_3-身份认证" class="sidebar-link">3.  身份认证</a></li><li class="sidebar-sub-header"><a href="/heima2020/node/day06.html#_4-session" class="sidebar-link">4.  session</a></li><li class="sidebar-sub-header"><a href="/heima2020/node/day06.html#_5-jwt" class="sidebar-link">5.  jwt</a></li><li class="sidebar-sub-header"><a href="/heima2020/node/day06.html#_6-项目初始化" class="sidebar-link">6. 项目初始化</a></li><li class="sidebar-sub-header"><a href="/heima2020/node/day06.html#_7-注册新用户" class="sidebar-link">7.  注册新用户</a></li><li class="sidebar-sub-header"><a href="/heima2020/node/day06.html#_8-优化" class="sidebar-link">8.  优化</a></li></ul></li></ul></li><li><a href="/heima2020/node/day07.html" class="sidebar-link">Node 第 7 天</a></li><li><a href="/heima2020/node/day08.html" class="sidebar-link">Node 第 8 天</a></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h2 id="node-第-6-天"><a href="#node-第-6-天" class="header-anchor">#</a> Node 第 6 天</h2> <h3 id="_1-学习目标"><a href="#_1-学习目标" class="header-anchor">#</a> 1.  学习目标</h3> <p>◆ 前后端的身份认证</p> <p>◆ 能够了解 Session 的实现原理</p> <p>◆ 能够了解 JWT 的实现原理</p> <p>◆ 大事件项目初始化</p> <p>◆ 大事件注册新用户功能</p> <h3 id="_2-web-开发模式"><a href="#_2-web-开发模式" class="header-anchor">#</a> 2.  web 开发模式</h3> <h4 id="_2-1-主流的两种开发模式"><a href="#_2-1-主流的两种开发模式" class="header-anchor">#</a> 2.1  主流的两种开发模式</h4> <ol><li>基于<strong>服务端渲染</strong>的传统 Web 开发模式</li> <li>基于<strong>前后端分离</strong>的新型 Web 开发模式</li></ol> <h4 id="_2-2-了解服务端渲染的概念以及优缺点"><a href="#_2-2-了解服务端渲染的概念以及优缺点" class="header-anchor">#</a> 2.2 了解服务端渲染的概念以及优缺点</h4> <ol><li>服务端渲染的概念：服务器发送给客户端的 <code>HTML</code> 页面，是在<strong>服务器通过字符串的拼接动态生成的</strong>。因此，客户端不需要使用 Ajax 这样的技术额外请求页面的数据</li></ol> <img src="/heima2020/assets/img/001 - 服务端渲染的 Web 开发模式.45afdf67.png" style="zoom:67%;"> <ol start="2"><li>服务端渲染的优点</li></ol> <ul><li><p><strong>前端耗时少</strong>。因为服务器端负责动态生成 HTML 内容，浏览器只需要直接渲染页面即可。尤其是移动端，更省电</p></li> <li><p><strong>有利于SEO</strong>。因为服务器端响应的是完整的 HTML 页面内容，所以爬虫更容易爬取获得信息，更有利于SEO</p></li></ul> <ol start="3"><li><p>服务端渲染的缺点</p> <ul><li><strong>占用服务器端资源</strong>。即服务器端完成 HTML 页面内容的拼接，如果请求较多，会对服务器造成一定的访问压力</li> <li><strong>不利于前后端分离，开发效率低</strong>。使用服务器端渲染，则无法进行分工合作，尤其对于前端复杂度高的项目，不利于项目高效开发</li></ul></li></ol> <h4 id="_2-3-了解前后端分离的概念以及优缺点"><a href="#_2-3-了解前后端分离的概念以及优缺点" class="header-anchor">#</a> 2.3 了解前后端分离的概念以及优缺点</h4> <ol><li><p>前后端分离的概念：前后端分离的开发模式，<strong>依赖于 Ajax 技术的广泛应用</strong>。简而言之，前后端分离的 Web 开发模式，就是<strong>后端只负责提供 API 接口，前端使用 Ajax 调用接口</strong>的开发模式</p></li> <li><p>前后端分离的优点</p></li></ol> <ul><li><p><strong>开发体验好</strong>。前端专注于 UI 页面的开发，后端专注于api 的开发，且前端有更多的选择性</p></li> <li><p><strong>用户体验好</strong>。Ajax 技术的广泛应用，极大的提高了用户的体验，可以轻松实现页面的局部刷新</p></li> <li><p><strong>减轻了服务器端的渲染压力</strong>。因为页面最终是在每个用户的浏览器中生成的</p></li></ul> <ol start="3"><li>前后端分离的缺点</li></ol> <ul><li><strong>不利于 SEO</strong>。因为完整的 HTML 页面需要在客户端动态拼接完成，所以爬虫对无法爬取页面的有效信息。（解决方案：利用 Vue、React 等前端框架的 <strong>SSR</strong> 技术能够很好的解决 SEO 问题！）</li></ul> <h4 id="_2-4-如何选择-web-开发模式"><a href="#_2-4-如何选择-web-开发模式" class="header-anchor">#</a> 2.4 如何选择 Web 开发模式</h4> <ol><li><strong>不谈业务场景而盲目选择使用何种开发模式都是耍流氓</strong></li></ol> <ul><li><p>比如企业级网站，主要功能是展示而没有复杂的交互，并且需要良好的 <code>SEO</code>，则这时我们就需要使用服务器端渲染</p></li> <li><p>而类似后台管理项目，交互性比较强，不需要考虑 <code>SEO</code>，那么就可以使用前后端分离的开发模式</p></li></ul> <ol start="2"><li>另外，具体使用何种开发模式并不是绝对的，为了<strong>同时兼顾</strong>了<strong>首页的渲染速度</strong>和<strong>前后端分离的开发效率</strong>，一些网站采用了首屏服务器端渲染 + 其他页面前后端分离的开发模式</li></ol> <h3 id="_3-身份认证"><a href="#_3-身份认证" class="header-anchor">#</a> 3.  身份认证</h3> <h4 id="_3-1-什么是身份认证"><a href="#_3-1-什么是身份认证" class="header-anchor">#</a> 3.1  什么是身份认证</h4> <ol><li>身份认证，又称 ”身份验证“，”鉴权“，是指通过一定的手段，完成对用户身份的确认，例如：</li></ol> <ul><li>各大网站的手机验证码登录</li> <li>邮箱密码登录</li> <li>二维码登录</li></ul> <h4 id="_3-2-为什么需要身份认证"><a href="#_3-2-为什么需要身份认证" class="header-anchor">#</a> 3.2 为什么需要身份认证</h4> <ol><li>身份认证的目的，是为了<strong>确认当前所声称为某种身份的用户，确实是所声称的用户</strong></li></ol> <ul><li>例如：你去找快递员取快递，你要怎么证明这份快递是你的</li></ul> <ol start="2"><li>不同开发模式下的身份认证</li></ol> <ul><li>对于<strong>服务端渲染</strong>和<strong>前后端分离</strong>这两种开发模式来说，分别有着不同的身份认证方案
<ul><li><strong>服务端渲染</strong> 推荐使用 <strong>Session 认证机制</strong></li> <li><strong>前后端分离</strong>推荐使用 <strong>JWT 认证机制</strong></li></ul></li></ul> <h3 id="_4-session"><a href="#_4-session" class="header-anchor">#</a> 4.  session</h3> <h4 id="_4-1-了解-http-协议的无状态性"><a href="#_4-1-了解-http-协议的无状态性" class="header-anchor">#</a> 4.1 了解 HTTP 协议的无状态性</h4> <ol><li><p>HTTP 协议的无状态性，指的是客户端的<strong>每次 HTTP 请求都是独立的</strong>，连续多个请求之间没有直接的关系，<strong>服务器不会主动保留每次 HTTP 请求的状态</strong></p> <img src="/heima2020/assets/img/002 - http协议无状态性.f7f738aa.png" style="zoom:67%;"></li></ol> <h4 id="_4-2-如何突破-http-无状态的限制"><a href="#_4-2-如何突破-http-无状态的限制" class="header-anchor">#</a> 4.2 如何突破 HTTP 无状态的限制</h4> <ol><li><p>对于超市来说，为了方便收银员在进行结算时给 <code>VIP</code> 用户打折，超市可以为每个 <code>VIP</code> 用户发放会员卡</p> <img src="/heima2020/assets/img/003 - 突破 HTTP 无状态的限制.bb8b45eb.png" style="zoom:67%;"></li> <li><p>注意：现实生活中的会员卡身份认证方式，在 <code>Web</code> 开发中的专业术语叫做 <code>Cookie</code></p></li></ol> <h4 id="_4-3-什么是-cookie"><a href="#_4-3-什么是-cookie" class="header-anchor">#</a> 4.3 什么是 Cookie</h4> <ol><li><code>Cookie</code> 是<strong>存储在用户浏览器中的一段不超过 4 KB 的字符串</strong>。它由一个<strong>名称</strong>（Name）、一个<strong>值</strong>（Value）和其它几个用于控制 Cookie <strong>有效期</strong>、<strong>安全性</strong>、<strong>使用范围</strong>的<strong>可选属性</strong>组成</li> <li>不同域名下的 Cookie 各自独立，每当客户端发起请求时，会<strong>自动</strong>把<strong>当前域名下</strong>所有<strong>未过期的 Cookie</strong> 一同发送到服务器</li> <li><code>Cookie</code> 的几大特性</li></ol> <ul><li>自动发送</li> <li>域名独立</li> <li>过期时限</li> <li>4KB 限制</li></ul> <h4 id="_4-4-cookie-在身份认证中的作用"><a href="#_4-4-cookie-在身份认证中的作用" class="header-anchor">#</a> 4.4 Cookie 在身份认证中的作用</h4> <ol><li><p>客户端第一次请求服务器的时候，服务器通过响应头的形式，向客户端发送一个身份认证的 <code>Cookie</code>，客户端会自动将 <code>Cookie</code> 保存在浏览器中。</p></li> <li><p>随后，当客户端浏览器每次请求服务器的时候，浏览器会自动将身份认证相关的 <code>Cookie</code>，通过请求头的形式发送给服务器，服务器即可验明客户端的身份</p></li></ol> <img src="/heima2020/assets/img/004 - Cookie 在身份认证中的作用.1839dffe.png" style="zoom:67%;"> <h4 id="_4-5-cookie-不具有安全性"><a href="#_4-5-cookie-不具有安全性" class="header-anchor">#</a> 4.5  Cookie 不具有安全性</h4> <ol><li><p>由于 <code>Cookie</code> 是存储在浏览器中的，而且浏览器也提供了读写 <code>Cookie</code> 的 <code>API</code>，因此 <code>Cookie</code> 很容易被伪造，不具有安全性。因此不建议服务器将重要的隐私数据通过 <code>Cookie</code> 的形式发送给浏览器</p></li> <li><p><strong>注意：千万不要使用 Cookie 存储重要且隐私的数据！</strong> 比如用户的身份信息、密码等</p></li></ol> <img src="/heima2020/assets/img/005 - Cookie 不具有安全性.4dc3d42e.png" style="zoom:67%;"> <h4 id="_4-6-提高身份认证的安全性"><a href="#_4-6-提高身份认证的安全性" class="header-anchor">#</a> 4.6 提高身份认证的安全性</h4> <ol><li>为了防止客户伪造会员卡，收银员在拿到客户出示的会员卡之后，可以在收银机上进行刷卡认证。只有收银机确认存在的会员卡，才能被正常使用</li></ol> <img src="/heima2020/assets/img/006 - 提高身份认证的安全性.2cc0b7f4.png" style="zoom:67%;"> <ol start="2"><li>这种“会员卡 + 刷卡认证”的设计理念，就是 <code>Session</code> 认证机制的精髓</li></ol> <h4 id="_4-7-session-的工作原理"><a href="#_4-7-session-的工作原理" class="header-anchor">#</a> 4.7 Session 的工作原理</h4> <img src="/heima2020/assets/img/007 - Session 的工作原理.5cffef54.png" style="zoom:67%;"> <h4 id="_4-8-安装并-express-session-中间件"><a href="#_4-8-安装并-express-session-中间件" class="header-anchor">#</a> 4.8 安装并 express-session 中间件</h4> <ol><li>安装 <code>express-session</code></li></ol> <div class="language-js extra-class"><pre class="language-js"><code>cnpm i express<span class="token operator">-</span>session <span class="token operator">--</span>save
</code></pre></div><ol start="2"><li>配置 <code>express-session</code> 中间件</li></ol> <ul><li><p><code>express-session</code> 中间件安装成功后，需要通过 <code>app.use()</code> 来注册 <code>session</code> 中间件</p> <img src="/heima2020/assets/img/008 - 配置 express-session 中间件.66af9577.png" style="zoom:67%;"></li></ul> <ol start="3"><li>案例代码</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 导入 express 模块</span>
<span class="token keyword">const</span> express <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'express'</span><span class="token punctuation">)</span>
<span class="token comment">// 创建 express 的服务器实例</span>
<span class="token keyword">const</span> app <span class="token operator">=</span> <span class="token function">express</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

<span class="token comment">// TODO_01：请配置 Session 中间件</span>
<span class="token keyword">const</span> session <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'express-session'</span><span class="token punctuation">)</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>
  <span class="token function">session</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
    secret<span class="token operator">:</span> <span class="token string">'itheima'</span><span class="token punctuation">,</span>
    resave<span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span>
    saveUninitialized<span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">)</span>

<span class="token comment">// 托管静态页面</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>express<span class="token punctuation">.</span><span class="token function">static</span><span class="token punctuation">(</span><span class="token string">'./pages'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token comment">// 解析 POST 提交过来的表单数据</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>express<span class="token punctuation">.</span><span class="token function">urlencoded</span><span class="token punctuation">(</span><span class="token punctuation">{</span> extended<span class="token operator">:</span> <span class="token boolean">false</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">)</span>

<span class="token comment">// 登录的 API 接口</span>
app<span class="token punctuation">.</span><span class="token function">post</span><span class="token punctuation">(</span><span class="token string">'/api/login'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">)</span>

<span class="token comment">// 获取用户姓名的接口</span>
app<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">'/api/username'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">)</span>

<span class="token comment">// 退出登录的接口</span>
app<span class="token punctuation">.</span><span class="token function">post</span><span class="token punctuation">(</span><span class="token string">'/api/logout'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">)</span>

<span class="token comment">// 调用 app.listen 方法，指定端口号并启动web服务器</span>
app<span class="token punctuation">.</span><span class="token function">listen</span><span class="token punctuation">(</span><span class="token number">80</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Express server running at http://127.0.0.1:80'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

</code></pre></div><h4 id="_4-9-向-session-中存数据"><a href="#_4-9-向-session-中存数据" class="header-anchor">#</a> 4.9  向 session 中存数据</h4> <ol><li><p>当 <code>express-session</code> 中间件配置成功后，即可通过 <code>req.session</code> 来访问和使用 <code>session</code> 对象，从而存储用户的关键信息</p></li> <li><p>示例</p></li></ol> <img src="/heima2020/assets/img/009 - 向 session 中存数据.77860453.png" style="zoom:67%;"> <ol start="3"><li><p>案例代码</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 导入 express 模块</span>
<span class="token keyword">const</span> express <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'express'</span><span class="token punctuation">)</span>
<span class="token comment">// 创建 express 的服务器实例</span>
<span class="token keyword">const</span> app <span class="token operator">=</span> <span class="token function">express</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

<span class="token comment">// TODO_01：请配置 Session 中间件</span>
<span class="token keyword">const</span> session <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'express-session'</span><span class="token punctuation">)</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>
  <span class="token function">session</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
    secret<span class="token operator">:</span> <span class="token string">'itheima'</span><span class="token punctuation">,</span>
    resave<span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span>
    saveUninitialized<span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">)</span>

<span class="token comment">// 托管静态页面</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>express<span class="token punctuation">.</span><span class="token function">static</span><span class="token punctuation">(</span><span class="token string">'./pages'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token comment">// 解析 POST 提交过来的表单数据</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>express<span class="token punctuation">.</span><span class="token function">urlencoded</span><span class="token punctuation">(</span><span class="token punctuation">{</span> extended<span class="token operator">:</span> <span class="token boolean">false</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">)</span>

<span class="token comment">// 登录的 API 接口</span>
app<span class="token punctuation">.</span><span class="token function">post</span><span class="token punctuation">(</span><span class="token string">'/api/login'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token comment">// 判断用户提交的登录信息是否正确</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span>req<span class="token punctuation">.</span>body<span class="token punctuation">.</span>username <span class="token operator">!==</span> <span class="token string">'admin'</span> <span class="token operator">||</span> req<span class="token punctuation">.</span>body<span class="token punctuation">.</span>password <span class="token operator">!==</span> <span class="token string">'000000'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token punctuation">{</span> status<span class="token operator">:</span> <span class="token number">1</span><span class="token punctuation">,</span> msg<span class="token operator">:</span> <span class="token string">'登录失败'</span> <span class="token punctuation">}</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span>

  <span class="token comment">// TODO_02：请将登录成功后的用户信息，保存到 Session 中</span>
  <span class="token comment">// 注意：只有成功配置了 express-session 这个中间件之后，才能够通过 req 点出来 session 这个属性</span>
  req<span class="token punctuation">.</span>session<span class="token punctuation">.</span>user <span class="token operator">=</span> req<span class="token punctuation">.</span>body <span class="token comment">// 用户的信息</span>
  req<span class="token punctuation">.</span>session<span class="token punctuation">.</span>islogin <span class="token operator">=</span> <span class="token boolean">true</span> <span class="token comment">// 用户的登录状态</span>

  res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token punctuation">{</span> status<span class="token operator">:</span> <span class="token number">0</span><span class="token punctuation">,</span> msg<span class="token operator">:</span> <span class="token string">'登录成功'</span> <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

<span class="token comment">// 获取用户姓名的接口</span>
app<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">'/api/username'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span> <span class="token punctuation">}</span><span class="token punctuation">)</span>

<span class="token comment">// 退出登录的接口</span>
app<span class="token punctuation">.</span><span class="token function">post</span><span class="token punctuation">(</span><span class="token string">'/api/logout'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span> <span class="token punctuation">}</span><span class="token punctuation">)</span>

<span class="token comment">// 调用 app.listen 方法，指定端口号并启动web服务器</span>
app<span class="token punctuation">.</span><span class="token function">listen</span><span class="token punctuation">(</span><span class="token number">80</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Express server running at http://127.0.0.1:80'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

</code></pre></div></li></ol> <h4 id="_4-10-从-session-中取数据"><a href="#_4-10-从-session-中取数据" class="header-anchor">#</a> 4.10 从 session 中取数据</h4> <ol><li><p>可以直接从 <code>req.session</code> 对象上获取之前存储的数据</p></li> <li><p>示例</p></li></ol> <img src="/heima2020/assets/img/010 - 从 session 中取数据.a9aaade3.png" style="zoom:67%;"> <ol start="3"><li>案例代码</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 导入 express 模块</span>
<span class="token keyword">const</span> express <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'express'</span><span class="token punctuation">)</span>
<span class="token comment">// 创建 express 的服务器实例</span>
<span class="token keyword">const</span> app <span class="token operator">=</span> <span class="token function">express</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

<span class="token comment">// TODO_01：请配置 Session 中间件</span>
<span class="token keyword">const</span> session <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'express-session'</span><span class="token punctuation">)</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>
  <span class="token function">session</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
    secret<span class="token operator">:</span> <span class="token string">'itheima'</span><span class="token punctuation">,</span>
    resave<span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span>
    saveUninitialized<span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">)</span>

<span class="token comment">// 托管静态页面</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>express<span class="token punctuation">.</span><span class="token function">static</span><span class="token punctuation">(</span><span class="token string">'./pages'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token comment">// 解析 POST 提交过来的表单数据</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>express<span class="token punctuation">.</span><span class="token function">urlencoded</span><span class="token punctuation">(</span><span class="token punctuation">{</span> extended<span class="token operator">:</span> <span class="token boolean">false</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">)</span>

<span class="token comment">// 登录的 API 接口</span>
app<span class="token punctuation">.</span><span class="token function">post</span><span class="token punctuation">(</span><span class="token string">'/api/login'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token comment">// 判断用户提交的登录信息是否正确</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span>req<span class="token punctuation">.</span>body<span class="token punctuation">.</span>username <span class="token operator">!==</span> <span class="token string">'admin'</span> <span class="token operator">||</span> req<span class="token punctuation">.</span>body<span class="token punctuation">.</span>password <span class="token operator">!==</span> <span class="token string">'000000'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token punctuation">{</span> status<span class="token operator">:</span> <span class="token number">1</span><span class="token punctuation">,</span> msg<span class="token operator">:</span> <span class="token string">'登录失败'</span> <span class="token punctuation">}</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span>

  <span class="token comment">// TODO_02：请将登录成功后的用户信息，保存到 Session 中</span>
  <span class="token comment">// 注意：只有成功配置了 express-session 这个中间件之后，才能够通过 req 点出来 session 这个属性</span>
  req<span class="token punctuation">.</span>session<span class="token punctuation">.</span>user <span class="token operator">=</span> req<span class="token punctuation">.</span>body <span class="token comment">// 用户的信息</span>
  req<span class="token punctuation">.</span>session<span class="token punctuation">.</span>islogin <span class="token operator">=</span> <span class="token boolean">true</span> <span class="token comment">// 用户的登录状态</span>

  res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token punctuation">{</span> status<span class="token operator">:</span> <span class="token number">0</span><span class="token punctuation">,</span> msg<span class="token operator">:</span> <span class="token string">'登录成功'</span> <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

<span class="token comment">// 获取用户姓名的接口</span>
app<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">'/api/username'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token comment">// TODO_03：请从 Session 中获取用户的名称，响应给客户端</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>req<span class="token punctuation">.</span>session<span class="token punctuation">.</span>islogin<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token punctuation">{</span> status<span class="token operator">:</span> <span class="token number">1</span><span class="token punctuation">,</span> msg<span class="token operator">:</span> <span class="token string">'fail'</span> <span class="token punctuation">}</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span>
  res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
    status<span class="token operator">:</span> <span class="token number">0</span><span class="token punctuation">,</span>
    msg<span class="token operator">:</span> <span class="token string">'success'</span><span class="token punctuation">,</span>
    username<span class="token operator">:</span> req<span class="token punctuation">.</span>session<span class="token punctuation">.</span>user<span class="token punctuation">.</span>username<span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

<span class="token comment">// 退出登录的接口</span>
app<span class="token punctuation">.</span><span class="token function">post</span><span class="token punctuation">(</span><span class="token string">'/api/logout'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span> <span class="token punctuation">}</span><span class="token punctuation">)</span>

<span class="token comment">// 调用 app.listen 方法，指定端口号并启动web服务器</span>
app<span class="token punctuation">.</span><span class="token function">listen</span><span class="token punctuation">(</span><span class="token number">80</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Express server running at http://127.0.0.1:80'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

</code></pre></div><h4 id="_4-11-清空-session"><a href="#_4-11-清空-session" class="header-anchor">#</a> 4.11 清空 session</h4> <ol><li><p>调用 <code>req.session.destroy()</code> 函数，即可清空服务器保存的 <code>session</code> 信息</p></li> <li><p>实例</p></li></ol> <img src="/heima2020/assets/img/011 - 清空 session.4ee83db3.png" style="zoom:67%;"> <ol start="3"><li>案例代码</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 导入 express 模块</span>
<span class="token keyword">const</span> express <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'express'</span><span class="token punctuation">)</span>
<span class="token comment">// 创建 express 的服务器实例</span>
<span class="token keyword">const</span> app <span class="token operator">=</span> <span class="token function">express</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

<span class="token comment">// TODO_01：请配置 Session 中间件</span>
<span class="token keyword">const</span> session <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'express-session'</span><span class="token punctuation">)</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>
  <span class="token function">session</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
    secret<span class="token operator">:</span> <span class="token string">'itheima'</span><span class="token punctuation">,</span>
    resave<span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span>
    saveUninitialized<span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">)</span>

<span class="token comment">// 托管静态页面</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>express<span class="token punctuation">.</span><span class="token function">static</span><span class="token punctuation">(</span><span class="token string">'./pages'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token comment">// 解析 POST 提交过来的表单数据</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>express<span class="token punctuation">.</span><span class="token function">urlencoded</span><span class="token punctuation">(</span><span class="token punctuation">{</span> extended<span class="token operator">:</span> <span class="token boolean">false</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">)</span>

<span class="token comment">// 登录的 API 接口</span>
app<span class="token punctuation">.</span><span class="token function">post</span><span class="token punctuation">(</span><span class="token string">'/api/login'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token comment">// 判断用户提交的登录信息是否正确</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span>req<span class="token punctuation">.</span>body<span class="token punctuation">.</span>username <span class="token operator">!==</span> <span class="token string">'admin'</span> <span class="token operator">||</span> req<span class="token punctuation">.</span>body<span class="token punctuation">.</span>password <span class="token operator">!==</span> <span class="token string">'000000'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token punctuation">{</span> status<span class="token operator">:</span> <span class="token number">1</span><span class="token punctuation">,</span> msg<span class="token operator">:</span> <span class="token string">'登录失败'</span> <span class="token punctuation">}</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span>

  <span class="token comment">// TODO_02：请将登录成功后的用户信息，保存到 Session 中</span>
  <span class="token comment">// 注意：只有成功配置了 express-session 这个中间件之后，才能够通过 req 点出来 session 这个属性</span>
  req<span class="token punctuation">.</span>session<span class="token punctuation">.</span>user <span class="token operator">=</span> req<span class="token punctuation">.</span>body <span class="token comment">// 用户的信息</span>
  req<span class="token punctuation">.</span>session<span class="token punctuation">.</span>islogin <span class="token operator">=</span> <span class="token boolean">true</span> <span class="token comment">// 用户的登录状态</span>

  res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token punctuation">{</span> status<span class="token operator">:</span> <span class="token number">0</span><span class="token punctuation">,</span> msg<span class="token operator">:</span> <span class="token string">'登录成功'</span> <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

<span class="token comment">// 获取用户姓名的接口</span>
app<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">'/api/username'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token comment">// TODO_03：请从 Session 中获取用户的名称，响应给客户端</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>req<span class="token punctuation">.</span>session<span class="token punctuation">.</span>islogin<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token punctuation">{</span> status<span class="token operator">:</span> <span class="token number">1</span><span class="token punctuation">,</span> msg<span class="token operator">:</span> <span class="token string">'fail'</span> <span class="token punctuation">}</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span>
  res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
    status<span class="token operator">:</span> <span class="token number">0</span><span class="token punctuation">,</span>
    msg<span class="token operator">:</span> <span class="token string">'success'</span><span class="token punctuation">,</span>
    username<span class="token operator">:</span> req<span class="token punctuation">.</span>session<span class="token punctuation">.</span>user<span class="token punctuation">.</span>username<span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

<span class="token comment">// 退出登录的接口</span>
app<span class="token punctuation">.</span><span class="token function">post</span><span class="token punctuation">(</span><span class="token string">'/api/logout'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token comment">// TODO_04：清空 Session 信息</span>
  req<span class="token punctuation">.</span>session<span class="token punctuation">.</span><span class="token function">destroy</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
    status<span class="token operator">:</span> <span class="token number">0</span><span class="token punctuation">,</span>
    msg<span class="token operator">:</span> <span class="token string">'退出登录成功'</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

<span class="token comment">// 调用 app.listen 方法，指定端口号并启动web服务器</span>
app<span class="token punctuation">.</span><span class="token function">listen</span><span class="token punctuation">(</span><span class="token number">80</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Express server running at http://127.0.0.1:80'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

</code></pre></div><h4 id="_4-12-演示-session-案例效果"><a href="#_4-12-演示-session-案例效果" class="header-anchor">#</a> 4.12 演示 session 案例效果</h4> <div class="language-html extra-class"><pre class="language-html"><code><span class="token comment">&lt;!-- index.html 页面 --&gt;</span>

<span class="token doctype"><span class="token punctuation">&lt;!</span><span class="token doctype-tag">DOCTYPE</span> <span class="token name">html</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>html</span> <span class="token attr-name">lang</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>en<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>

<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>head</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>meta</span> <span class="token attr-name">charset</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>UTF-8<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>meta</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>viewport<span class="token punctuation">&quot;</span></span> <span class="token attr-name">content</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>width=device-width, initial-scale=1.0<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>title</span><span class="token punctuation">&gt;</span></span>后台主页<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>title</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>./jquery.js<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span><span class="token script"></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>head</span><span class="token punctuation">&gt;</span></span>

<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>body</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>h1</span><span class="token punctuation">&gt;</span></span>首页<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>h1</span><span class="token punctuation">&gt;</span></span>

  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>button</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>btnLogin<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>退出登录<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>button</span><span class="token punctuation">&gt;</span></span>

  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">&gt;</span></span><span class="token script"><span class="token language-javascript">
    <span class="token function">$</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token comment">// 初始化方法</span>
      <span class="token keyword">function</span> <span class="token function">init</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        $<span class="token punctuation">.</span><span class="token function">ajax</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
          url<span class="token operator">:</span> <span class="token string">'/api/username'</span><span class="token punctuation">,</span>
          type<span class="token operator">:</span> <span class="token string">'get'</span><span class="token punctuation">,</span>
          <span class="token function-variable function">success</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token parameter">data</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
            <span class="token comment">// console.log(data)</span>
            <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>data<span class="token punctuation">.</span>status<span class="token punctuation">)</span> <span class="token punctuation">{</span>
              <span class="token function">alert</span><span class="token punctuation">(</span><span class="token string">'欢迎登录：'</span> <span class="token operator">+</span> data<span class="token punctuation">.</span>username<span class="token punctuation">)</span>
            <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
              <span class="token function">alert</span><span class="token punctuation">(</span><span class="token string">'您尚未登录，请登录后在执行此操作！'</span><span class="token punctuation">)</span>
              window<span class="token punctuation">.</span>location<span class="token punctuation">.</span>href <span class="token operator">=</span> <span class="token string">'/login.html'</span>
            <span class="token punctuation">}</span>
          <span class="token punctuation">}</span>
        <span class="token punctuation">}</span><span class="token punctuation">)</span>
      <span class="token punctuation">}</span>
      <span class="token function">init</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

      <span class="token comment">// 退出登录</span>
      <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">'#btnLogin'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">click</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
        $<span class="token punctuation">.</span><span class="token function">ajax</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
          url<span class="token operator">:</span> <span class="token string">'/api/logout'</span><span class="token punctuation">,</span>
          type<span class="token operator">:</span> <span class="token string">'post'</span><span class="token punctuation">,</span>
          <span class="token function-variable function">success</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token parameter">data</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
            <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>data<span class="token punctuation">.</span>status<span class="token punctuation">)</span> <span class="token punctuation">{</span>
              <span class="token function">alert</span><span class="token punctuation">(</span>data<span class="token punctuation">.</span>msg<span class="token punctuation">)</span>
              window<span class="token punctuation">.</span>location<span class="token punctuation">.</span>href <span class="token operator">=</span> <span class="token string">'/login.html'</span>
            <span class="token punctuation">}</span>
          <span class="token punctuation">}</span>
        <span class="token punctuation">}</span><span class="token punctuation">)</span>
      <span class="token punctuation">}</span><span class="token punctuation">)</span>

    <span class="token punctuation">}</span><span class="token punctuation">)</span>
  </span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>body</span><span class="token punctuation">&gt;</span></span>

<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>html</span><span class="token punctuation">&gt;</span></span>
</code></pre></div><div class="language-html extra-class"><pre class="language-html"><code><span class="token comment">&lt;!-- login.html 页面 --&gt;</span>

<span class="token doctype"><span class="token punctuation">&lt;!</span><span class="token doctype-tag">DOCTYPE</span> <span class="token name">html</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>html</span> <span class="token attr-name">lang</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>en<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>

<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>head</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>meta</span> <span class="token attr-name">charset</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>UTF-8<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>meta</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>viewport<span class="token punctuation">&quot;</span></span> <span class="token attr-name">content</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>width=device-width, initial-scale=1.0<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>title</span><span class="token punctuation">&gt;</span></span>登录页面<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>title</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>./jquery.js<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span><span class="token script"></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>head</span><span class="token punctuation">&gt;</span></span>

<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>body</span><span class="token punctuation">&gt;</span></span>
  <span class="token comment">&lt;!-- 登录表单 --&gt;</span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>form</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>form1<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span><span class="token punctuation">&gt;</span></span>账号：<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>input</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>text<span class="token punctuation">&quot;</span></span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>username<span class="token punctuation">&quot;</span></span> <span class="token attr-name">autocomplete</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>off<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span> <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span><span class="token punctuation">&gt;</span></span>密码：<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>input</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>password<span class="token punctuation">&quot;</span></span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>password<span class="token punctuation">&quot;</span></span> <span class="token attr-name">autocomplete</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>off<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>button</span><span class="token punctuation">&gt;</span></span>登录<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>button</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>form</span><span class="token punctuation">&gt;</span></span>

  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">&gt;</span></span><span class="token script"><span class="token language-javascript">
    <span class="token function">$</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">'button'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">click</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">e</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
        <span class="token comment">// 阻止默认行为</span>
        e<span class="token punctuation">.</span><span class="token function">preventDefault</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
        <span class="token comment">// 获取需要传递的参数</span>
        <span class="token keyword">const</span> params <span class="token operator">=</span> <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">'#form1'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">serialize</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
        <span class="token comment">// 发送 ajax </span>
        $<span class="token punctuation">.</span><span class="token function">ajax</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
          url<span class="token operator">:</span> <span class="token string">'/api/login'</span><span class="token punctuation">,</span>
          type<span class="token operator">:</span> <span class="token string">'post'</span><span class="token punctuation">,</span>
          data<span class="token operator">:</span> params<span class="token punctuation">,</span>
          <span class="token function-variable function">success</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token parameter">data</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
            window<span class="token punctuation">.</span>location<span class="token punctuation">.</span>href <span class="token operator">=</span> <span class="token string">'/index.html'</span>
          <span class="token punctuation">}</span>
        <span class="token punctuation">}</span><span class="token punctuation">)</span>
      <span class="token punctuation">}</span><span class="token punctuation">)</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span>
  </span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>body</span><span class="token punctuation">&gt;</span></span>

<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>html</span><span class="token punctuation">&gt;</span></span>
</code></pre></div><h3 id="_5-jwt"><a href="#_5-jwt" class="header-anchor">#</a> 5.  jwt</h3> <h4 id="_5-1-了解-session-认证的局限性"><a href="#_5-1-了解-session-认证的局限性" class="header-anchor">#</a> 5.1  了解 Session 认证的局限性</h4> <ol><li><code>Session</code> 认证机制需要配合 <code>Cookie</code> 才能实现。由于 <code>Cookie</code> 默认不支持跨域访问，所以，当涉及到前端跨域请求后端接口的时候，需要做很多额外的配置，才能实现跨域 <code>Session</code> 认证</li> <li>注意：</li></ol> <ul><li>当前端请求后端接口<strong>不存在跨域问题</strong>的时候，<strong>推荐使用 Session</strong> 身份认证机制</li> <li>前端<strong>需要跨域请求后端接口</strong>的时候，不推荐使用 Session 身份认证机制，<strong>推荐使用 JWT 认证机制</strong></li></ul> <ol start="3"><li>什么是 JWT</li></ol> <ul><li><code>JWT</code>（英文全称：<code>JSON Web Token</code>）是目前最流行的跨域认证解决方案</li></ul> <h4 id="_5-2-jwt-的工作原理"><a href="#_5-2-jwt-的工作原理" class="header-anchor">#</a> 5.2  JWT 的工作原理</h4> <ol><li>用户的信息通过 <code>Token</code> 字符串的形式，保存在客户端浏览器中</li> <li>服务器通过还原 <code>Token</code> 字符串的形式来认证用户的身份</li></ol> <img src="/heima2020/assets/img/012 - JWT 的工作原理.82e1a30a.png" style="zoom:67%;"> <h4 id="_5-3-jwt-的组成部分"><a href="#_5-3-jwt-的组成部分" class="header-anchor">#</a> 5.3  JWT 的组成部分</h4> <ol><li><p><code>JWT</code> 通常由三部分组成，分别是 <code>Header</code>（头部）、<code>Payload</code>（有效荷载）、<code>Signature</code>（签名）</p></li> <li><p>三者之间使用英文的“.”分隔，格式如下</p></li></ol> <img src="/heima2020/assets/img/012 - JWT 的组成部分.0ec6eab6.png" style="zoom:67%;"> <ol start="3"><li>下面是 <code>JWT</code> 字符串的示例</li></ol> <img src="/heima2020/assets/img/013 -  JWT 的组成部分.4c6b7d44.png" style="zoom:67%;"> <ol start="4"><li><code>JWT</code> 的三个组成部分，从前到后分别是 <code>Header</code>、<code>Payload</code>、<code>Signature</code></li></ol> <ul><li><p><code>Payload</code> 部分才是真正的用户信息，它是用户信息经过加密之后生成的字符串</p></li> <li><p><code>Header</code> 和 <code>Signature</code> 是安全性相关的部分，只是为了保证 <code>Token</code> 的安全性</p> <img src="/heima2020/assets/img/014 - JWT 的三个部分各自代表的含义.c509b7c4.png" style="zoom:67%;"></li></ul> <h4 id="_5-4-jwt-的使用方式"><a href="#_5-4-jwt-的使用方式" class="header-anchor">#</a> 5.4  JWT 的使用方式</h4> <ol><li><p>客户端收到服务器返回的 <code>JWT</code> 之后，通常会将它储存在 <code>localStorage</code> 或 <code>sessionStorage</code> 中</p></li> <li><p>此后，客户端每次与服务器通信，都要带上这个 <code>JWT</code> 的字符串，从而进行身份认证。推荐的做法是把<code>JWT</code> 放在 <code>HTTP</code> 请求头的 <code>Authorization</code> 字段中</p></li></ol> <img src="/heima2020/assets/img/015 - JWT 的使用方式.adceccda.png" style="zoom:67%;"> <h4 id="_5-5-安装并导入-jwt-相关的包"><a href="#_5-5-安装并导入-jwt-相关的包" class="header-anchor">#</a> 5.5 安装并导入 JWT 相关的包</h4> <h5 id="_5-5-1-安装-jwt-相关的包"><a href="#_5-5-1-安装-jwt-相关的包" class="header-anchor">#</a> 5.5.1 安装 JWT 相关的包</h5> <ol><li>运行如下命令，安装如下两个 JWT 相关的包</li></ol> <div class="language-js extra-class"><pre class="language-js"><code>cnpm i jsonwebtoken express<span class="token operator">-</span>jwt <span class="token operator">-</span><span class="token constant">S</span>
</code></pre></div> <img src="/heima2020/assets/img/016 - 安装 JWT 相关的包.a84280a4.png" style="zoom:67%;"> <ol start="2"><li>其中</li></ol> <ul><li><code>jsonwebtoken</code> 用于生成 <code>JWT</code> 字符串</li> <li><code>express-jwt</code> 用于将 <code>JWT</code> 字符串解析还原成 <code>JSON</code> 对象</li></ul> <h5 id="_5-5-2-导入-jwt-相关的包"><a href="#_5-5-2-导入-jwt-相关的包" class="header-anchor">#</a> 5.5.2  导入 JWT 相关的包</h5> <ol><li><p>使用 <code>require()</code> 函数，分别导入 <code>JWT</code> 相关的两个包</p></li> <li><p>实例</p> <img src="/heima2020/assets/img/017 - 导入 JWT 相关的包.d91d3b2b.png" style="zoom:67%;"></li> <li><p>案例代码</p></li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 导入 express 模块</span>
<span class="token keyword">const</span> express <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'express'</span><span class="token punctuation">)</span>
<span class="token comment">// 创建 express 的服务器实例</span>
<span class="token keyword">const</span> app <span class="token operator">=</span> <span class="token function">express</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

<span class="token comment">// TODO_01：安装并导入 JWT 相关的两个包，分别是 jsonwebtoken 和 express-jwt</span>
<span class="token keyword">const</span> jwt <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'jsonwebtoken'</span><span class="token punctuation">)</span>
<span class="token keyword">const</span> expressJWT <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'express-jwt'</span><span class="token punctuation">)</span>

<span class="token comment">// 允许跨域资源共享</span>
<span class="token keyword">const</span> cors <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'cors'</span><span class="token punctuation">)</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span><span class="token function">cors</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>

<span class="token comment">// 托管静态页面</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>express<span class="token punctuation">.</span><span class="token function">static</span><span class="token punctuation">(</span><span class="token string">'./pages'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token comment">// 解析 POST 提交过来的表单数据</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>express<span class="token punctuation">.</span><span class="token function">urlencoded</span><span class="token punctuation">(</span><span class="token punctuation">{</span> extended<span class="token operator">:</span> <span class="token boolean">false</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">)</span>



<span class="token comment">// 调用 app.listen 方法，指定端口号并启动web服务器</span>
app<span class="token punctuation">.</span><span class="token function">listen</span><span class="token punctuation">(</span><span class="token number">80</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Express server running at http://127.0.0.1:80'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

</code></pre></div><h4 id="_5-6-定义-secret-密钥"><a href="#_5-6-定义-secret-密钥" class="header-anchor">#</a> 5.6  定义 secret 密钥</h4> <ol><li>为了保证 <code>JWT</code>字符串的安全性，防止 JWT 字符串在网络传输过程中被别人破解，我们需要专门定义一个用于加密和解密的 <code>secret</code> 密钥</li></ol> <ul><li><p>当生成 <code>JWT</code> 字符串的时候，需要使用 <code>secret</code> 密钥对用户信息进行加密，最终得到加密好的 JWT 字符串</p></li> <li><p>当把 <code>JWT</code> 字符串解析还原成 <code>JSON</code> 对象的时候，需要使用 <code>secret</code> 密钥进行解密</p></li></ul> <img src="/heima2020/assets/img/018 - 定义 secret 密钥.7a990486.png" style="zoom:67%;"> <ol start="2"><li>案例代码</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 导入 express 模块</span>
<span class="token keyword">const</span> express <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'express'</span><span class="token punctuation">)</span>
<span class="token comment">// 创建 express 的服务器实例</span>
<span class="token keyword">const</span> app <span class="token operator">=</span> <span class="token function">express</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

<span class="token comment">// TODO_01：安装并导入 JWT 相关的两个包，分别是 jsonwebtoken 和 express-jwt</span>
<span class="token keyword">const</span> jwt <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'jsonwebtoken'</span><span class="token punctuation">)</span>
<span class="token keyword">const</span> expressJWT <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'express-jwt'</span><span class="token punctuation">)</span>

<span class="token comment">// 允许跨域资源共享</span>
<span class="token keyword">const</span> cors <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'cors'</span><span class="token punctuation">)</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span><span class="token function">cors</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>

<span class="token comment">// 托管静态页面</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>express<span class="token punctuation">.</span><span class="token function">static</span><span class="token punctuation">(</span><span class="token string">'./pages'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token comment">// 解析 POST 提交过来的表单数据</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>express<span class="token punctuation">.</span><span class="token function">urlencoded</span><span class="token punctuation">(</span><span class="token punctuation">{</span> extended<span class="token operator">:</span> <span class="token boolean">false</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">)</span>

<span class="token comment">// TODO_02：定义 secret 密钥，建议将密钥命名为 secretKey</span>
<span class="token keyword">const</span> secretKey <span class="token operator">=</span> <span class="token string">'itheima No1 ^_^'</span>


<span class="token comment">// 调用 app.listen 方法，指定端口号并启动web服务器</span>
app<span class="token punctuation">.</span><span class="token function">listen</span><span class="token punctuation">(</span><span class="token number">80</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Express server running at http://127.0.0.1:80'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

</code></pre></div><h4 id="_5-7-在登录成功后生成-jwt-字符串"><a href="#_5-7-在登录成功后生成-jwt-字符串" class="header-anchor">#</a> 5.7  在登录成功后生成 JWT 字符串</h4> <ol><li><p>调用 <code>jsonwebtoken</code> 包提供的 <code>sign()</code> 方法，将用户的信息加密成 <code>JWT</code> 字符串，响应给客户端</p></li> <li><p>示例</p></li></ol> <img src="/heima2020/assets/img/019 - 在登录成功后生成 JWT 字符串.1af765c7.png" style="zoom:67%;"> <ol start="3"><li>案例代码</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 导入 express 模块</span>
<span class="token keyword">const</span> express <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'express'</span><span class="token punctuation">)</span>
<span class="token comment">// 创建 express 的服务器实例</span>
<span class="token keyword">const</span> app <span class="token operator">=</span> <span class="token function">express</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

<span class="token comment">// TODO_01：安装并导入 JWT 相关的两个包，分别是 jsonwebtoken 和 express-jwt</span>
<span class="token keyword">const</span> jwt <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'jsonwebtoken'</span><span class="token punctuation">)</span>
<span class="token keyword">const</span> expressJWT <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'express-jwt'</span><span class="token punctuation">)</span>

<span class="token comment">// 允许跨域资源共享</span>
<span class="token keyword">const</span> cors <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'cors'</span><span class="token punctuation">)</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span><span class="token function">cors</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>

<span class="token comment">// 托管静态页面</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>express<span class="token punctuation">.</span><span class="token function">static</span><span class="token punctuation">(</span><span class="token string">'./pages'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token comment">// 解析 POST 提交过来的表单数据</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>express<span class="token punctuation">.</span><span class="token function">urlencoded</span><span class="token punctuation">(</span><span class="token punctuation">{</span> extended<span class="token operator">:</span> <span class="token boolean">false</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">)</span>

<span class="token comment">// TODO_02：定义 secret 密钥，建议将密钥命名为 secretKey</span>
<span class="token keyword">const</span> secretKey <span class="token operator">=</span> <span class="token string">'itheima No1 ^_^'</span>

<span class="token comment">// 登录接口</span>
app<span class="token punctuation">.</span><span class="token function">post</span><span class="token punctuation">(</span><span class="token string">'/api/login'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token comment">// 将 req.body 请求体中的数据，转存为 userinfo 常量</span>
  <span class="token keyword">const</span> userinfo <span class="token operator">=</span> req<span class="token punctuation">.</span>body
  <span class="token comment">// 登录失败</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span>userinfo<span class="token punctuation">.</span>username <span class="token operator">!==</span> <span class="token string">'admin'</span> <span class="token operator">||</span> userinfo<span class="token punctuation">.</span>password <span class="token operator">!==</span> <span class="token string">'000000'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
      status<span class="token operator">:</span> <span class="token number">400</span><span class="token punctuation">,</span>
      message<span class="token operator">:</span> <span class="token string">'登录失败！'</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span>
  <span class="token comment">// 登录成功</span>
  <span class="token comment">// TODO_03：在登录成功之后，调用 jwt.sign() 方法生成 JWT 字符串。并通过 token 属性发送给客户端</span>
  <span class="token comment">// 参数1：用户的信息对象</span>
  <span class="token comment">// 参数2：加密的秘钥</span>
  <span class="token comment">// 参数3：配置对象，可以配置当前 token 的有效期</span>
  <span class="token comment">// 记住：千万不要把密码加密到 token 字符中</span>
  <span class="token keyword">const</span> tokenStr <span class="token operator">=</span> jwt<span class="token punctuation">.</span><span class="token function">sign</span><span class="token punctuation">(</span><span class="token punctuation">{</span> username<span class="token operator">:</span> userinfo<span class="token punctuation">.</span>username <span class="token punctuation">}</span><span class="token punctuation">,</span> secretKey<span class="token punctuation">,</span> <span class="token punctuation">{</span> expiresIn<span class="token operator">:</span> <span class="token string">'30s'</span> <span class="token punctuation">}</span><span class="token punctuation">)</span>
  res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
    status<span class="token operator">:</span> <span class="token number">200</span><span class="token punctuation">,</span>
    message<span class="token operator">:</span> <span class="token string">'登录成功！'</span><span class="token punctuation">,</span>
    token<span class="token operator">:</span> tokenStr<span class="token punctuation">,</span> <span class="token comment">// 要发送给客户端的 token 字符串</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>


<span class="token comment">// 调用 app.listen 方法，指定端口号并启动web服务器</span>
app<span class="token punctuation">.</span><span class="token function">listen</span><span class="token punctuation">(</span><span class="token number">80</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Express server running at http://127.0.0.1:80'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

</code></pre></div><h4 id="_5-8-将-jwt-字符串还原为-json-对象"><a href="#_5-8-将-jwt-字符串还原为-json-对象" class="header-anchor">#</a> 5.8  将 JWT 字符串还原为 JSON 对象</h4> <ol><li><p>客户端每次在访问那些有权限接口的时候，都需要主动通过请求头中的 <code>Authorization</code> 字段，将 <code>Token</code> 字符串发送到服务器进行身份认证</p></li> <li><p>此时，服务器可以通过 <code>express-jwt</code> 这个中间件，自动将客户端发送过来的  <code>Token</code> 解析还原成 <code>JSON</code> 对象</p></li> <li><p>示例</p></li></ol> <img src="/heima2020/assets/img/020 - 将 JWT 字符串还原为 JSON 对象.59900e39.png" style="zoom:67%;"> <ol start="4"><li>案例代码</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 导入 express 模块</span>
<span class="token keyword">const</span> express <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'express'</span><span class="token punctuation">)</span>
<span class="token comment">// 创建 express 的服务器实例</span>
<span class="token keyword">const</span> app <span class="token operator">=</span> <span class="token function">express</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

<span class="token comment">// TODO_01：安装并导入 JWT 相关的两个包，分别是 jsonwebtoken 和 express-jwt</span>
<span class="token keyword">const</span> jwt <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'jsonwebtoken'</span><span class="token punctuation">)</span>
<span class="token keyword">const</span> expressJWT <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'express-jwt'</span><span class="token punctuation">)</span>

<span class="token comment">// 允许跨域资源共享</span>
<span class="token keyword">const</span> cors <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'cors'</span><span class="token punctuation">)</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span><span class="token function">cors</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>

<span class="token comment">// 托管静态页面</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>express<span class="token punctuation">.</span><span class="token function">static</span><span class="token punctuation">(</span><span class="token string">'./pages'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token comment">// 解析 POST 提交过来的表单数据</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>express<span class="token punctuation">.</span><span class="token function">urlencoded</span><span class="token punctuation">(</span><span class="token punctuation">{</span> extended<span class="token operator">:</span> <span class="token boolean">false</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">)</span>

<span class="token comment">// TODO_02：定义 secret 密钥，建议将密钥命名为 secretKey</span>
<span class="token keyword">const</span> secretKey <span class="token operator">=</span> <span class="token string">'itheima No1 ^_^'</span>

<span class="token comment">// TODO_04：注册将 JWT 字符串解析还原成 JSON 对象的中间件</span>
<span class="token comment">// 注意：只要配置成功了 express-jwt 这个中间件，就可以把解析出来的用户信息，挂载到 req.user 属性上</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span><span class="token function">expressJWT</span><span class="token punctuation">(</span><span class="token punctuation">{</span> secret<span class="token operator">:</span> secretKey <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">unless</span><span class="token punctuation">(</span><span class="token punctuation">{</span> path<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token regex">/^\/api\//</span><span class="token punctuation">]</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">)</span>

<span class="token comment">// 登录接口</span>
app<span class="token punctuation">.</span><span class="token function">post</span><span class="token punctuation">(</span><span class="token string">'/api/login'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token comment">// 将 req.body 请求体中的数据，转存为 userinfo 常量</span>
  <span class="token keyword">const</span> userinfo <span class="token operator">=</span> req<span class="token punctuation">.</span>body
  <span class="token comment">// 登录失败</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span>userinfo<span class="token punctuation">.</span>username <span class="token operator">!==</span> <span class="token string">'admin'</span> <span class="token operator">||</span> userinfo<span class="token punctuation">.</span>password <span class="token operator">!==</span> <span class="token string">'000000'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
      status<span class="token operator">:</span> <span class="token number">400</span><span class="token punctuation">,</span>
      message<span class="token operator">:</span> <span class="token string">'登录失败！'</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span>
  <span class="token comment">// 登录成功</span>
  <span class="token comment">// TODO_03：在登录成功之后，调用 jwt.sign() 方法生成 JWT 字符串。并通过 token 属性发送给客户端</span>
  <span class="token comment">// 参数1：用户的信息对象</span>
  <span class="token comment">// 参数2：加密的秘钥</span>
  <span class="token comment">// 参数3：配置对象，可以配置当前 token 的有效期</span>
  <span class="token comment">// 记住：千万不要把密码加密到 token 字符中</span>
  <span class="token keyword">const</span> tokenStr <span class="token operator">=</span> jwt<span class="token punctuation">.</span><span class="token function">sign</span><span class="token punctuation">(</span><span class="token punctuation">{</span> username<span class="token operator">:</span> userinfo<span class="token punctuation">.</span>username <span class="token punctuation">}</span><span class="token punctuation">,</span> secretKey<span class="token punctuation">,</span> <span class="token punctuation">{</span> expiresIn<span class="token operator">:</span> <span class="token string">'30s'</span> <span class="token punctuation">}</span><span class="token punctuation">)</span>
  res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
    status<span class="token operator">:</span> <span class="token number">200</span><span class="token punctuation">,</span>
    message<span class="token operator">:</span> <span class="token string">'登录成功！'</span><span class="token punctuation">,</span>
    token<span class="token operator">:</span> tokenStr<span class="token punctuation">,</span> <span class="token comment">// 要发送给客户端的 token 字符串</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>


<span class="token comment">// 调用 app.listen 方法，指定端口号并启动web服务器</span>
app<span class="token punctuation">.</span><span class="token function">listen</span><span class="token punctuation">(</span><span class="token number">80</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Express server running at http://127.0.0.1:80'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

</code></pre></div><h4 id="_5-9-使用-req-user-获取用户信息"><a href="#_5-9-使用-req-user-获取用户信息" class="header-anchor">#</a> 5.9  使用 req.user 获取用户信息</h4> <ol><li><p>当 <code>express-jwt</code> 这个中间件配置成功之后，即可在那些有权限的接口中，使用 <code>req.user</code> 对象，来访问从 <code>JWT</code> 字符串中解析出来的用户信息了</p></li> <li><p>实例</p></li></ol> <img src="/heima2020/assets/img/021 - 使用 req.user 获取用户信息.07632c6b.png" style="zoom:67%;"> <ol start="3"><li>案例代码</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 导入 express 模块</span>
<span class="token keyword">const</span> express <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'express'</span><span class="token punctuation">)</span>
<span class="token comment">// 创建 express 的服务器实例</span>
<span class="token keyword">const</span> app <span class="token operator">=</span> <span class="token function">express</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

<span class="token comment">// TODO_01：安装并导入 JWT 相关的两个包，分别是 jsonwebtoken 和 express-jwt</span>
<span class="token keyword">const</span> jwt <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'jsonwebtoken'</span><span class="token punctuation">)</span>
<span class="token keyword">const</span> expressJWT <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'express-jwt'</span><span class="token punctuation">)</span>

<span class="token comment">// 允许跨域资源共享</span>
<span class="token keyword">const</span> cors <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'cors'</span><span class="token punctuation">)</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span><span class="token function">cors</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>

<span class="token comment">// 托管静态页面</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>express<span class="token punctuation">.</span><span class="token function">static</span><span class="token punctuation">(</span><span class="token string">'./pages'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token comment">// 解析 POST 提交过来的表单数据</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>express<span class="token punctuation">.</span><span class="token function">urlencoded</span><span class="token punctuation">(</span><span class="token punctuation">{</span> extended<span class="token operator">:</span> <span class="token boolean">false</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">)</span>

<span class="token comment">// TODO_02：定义 secret 密钥，建议将密钥命名为 secretKey</span>
<span class="token keyword">const</span> secretKey <span class="token operator">=</span> <span class="token string">'itheima No1 ^_^'</span>

<span class="token comment">// TODO_04：注册将 JWT 字符串解析还原成 JSON 对象的中间件</span>
<span class="token comment">// 注意：只要配置成功了 express-jwt 这个中间件，就可以把解析出来的用户信息，挂载到 req.user 属性上</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span><span class="token function">expressJWT</span><span class="token punctuation">(</span><span class="token punctuation">{</span> secret<span class="token operator">:</span> secretKey <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">unless</span><span class="token punctuation">(</span><span class="token punctuation">{</span> path<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token regex">/^\/api\//</span><span class="token punctuation">]</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">)</span>

<span class="token comment">// 登录接口</span>
app<span class="token punctuation">.</span><span class="token function">post</span><span class="token punctuation">(</span><span class="token string">'/api/login'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token comment">// 将 req.body 请求体中的数据，转存为 userinfo 常量</span>
  <span class="token keyword">const</span> userinfo <span class="token operator">=</span> req<span class="token punctuation">.</span>body
  <span class="token comment">// 登录失败</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span>userinfo<span class="token punctuation">.</span>username <span class="token operator">!==</span> <span class="token string">'admin'</span> <span class="token operator">||</span> userinfo<span class="token punctuation">.</span>password <span class="token operator">!==</span> <span class="token string">'000000'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
      status<span class="token operator">:</span> <span class="token number">400</span><span class="token punctuation">,</span>
      message<span class="token operator">:</span> <span class="token string">'登录失败！'</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span>
  <span class="token comment">// 登录成功</span>
  <span class="token comment">// TODO_03：在登录成功之后，调用 jwt.sign() 方法生成 JWT 字符串。并通过 token 属性发送给客户端</span>
  <span class="token comment">// 参数1：用户的信息对象</span>
  <span class="token comment">// 参数2：加密的秘钥</span>
  <span class="token comment">// 参数3：配置对象，可以配置当前 token 的有效期</span>
  <span class="token comment">// 记住：千万不要把密码加密到 token 字符中</span>
  <span class="token keyword">const</span> tokenStr <span class="token operator">=</span> jwt<span class="token punctuation">.</span><span class="token function">sign</span><span class="token punctuation">(</span><span class="token punctuation">{</span> username<span class="token operator">:</span> userinfo<span class="token punctuation">.</span>username <span class="token punctuation">}</span><span class="token punctuation">,</span> secretKey<span class="token punctuation">,</span> <span class="token punctuation">{</span> expiresIn<span class="token operator">:</span> <span class="token string">'30s'</span> <span class="token punctuation">}</span><span class="token punctuation">)</span>
  res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
    status<span class="token operator">:</span> <span class="token number">200</span><span class="token punctuation">,</span>
    message<span class="token operator">:</span> <span class="token string">'登录成功！'</span><span class="token punctuation">,</span>
    token<span class="token operator">:</span> tokenStr<span class="token punctuation">,</span> <span class="token comment">// 要发送给客户端的 token 字符串</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

<span class="token comment">// 这是一个有权限的 API 接口</span>
app<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">'/admin/getinfo'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token comment">// TODO_05：使用 req.user 获取用户信息，并使用 data 属性将用户信息发送给客户端</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>req<span class="token punctuation">.</span>user<span class="token punctuation">)</span>
  res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
    status<span class="token operator">:</span> <span class="token number">200</span><span class="token punctuation">,</span>
    message<span class="token operator">:</span> <span class="token string">'获取用户信息成功！'</span><span class="token punctuation">,</span>
    data<span class="token operator">:</span> req<span class="token punctuation">.</span>user<span class="token punctuation">,</span> <span class="token comment">// 要发送给客户端的用户信息</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

<span class="token comment">// 调用 app.listen 方法，指定端口号并启动web服务器</span>
app<span class="token punctuation">.</span><span class="token function">listen</span><span class="token punctuation">(</span><span class="token number">80</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Express server running at http://127.0.0.1:80'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

</code></pre></div><h4 id="_5-10-捕获解析-jwt-失败后产生的错误"><a href="#_5-10-捕获解析-jwt-失败后产生的错误" class="header-anchor">#</a> 5.10 捕获解析 JWT 失败后产生的错误</h4> <ol><li><p>当使用 <code>express-jwt</code> 解析 <code>Token</code> 字符串时，如果客户端发送过来的 <code>Token</code> 字符串过期或不合法，会产生一个解析失败的错误，影响项目的正常运行</p></li> <li><p>可以通过 <code>Express</code> 的错误中间件，捕获这个错误并进行相关的处理</p></li> <li><p>示例</p></li></ol> <img src="/heima2020/assets/img/022 - 捕获解析 JWT 失败后产生的错误.947a152a.png" style="zoom:67%;"> <ol start="4"><li>案例代码</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 导入 express 模块</span>
<span class="token keyword">const</span> express <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'express'</span><span class="token punctuation">)</span>
<span class="token comment">// 创建 express 的服务器实例</span>
<span class="token keyword">const</span> app <span class="token operator">=</span> <span class="token function">express</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

<span class="token comment">// TODO_01：安装并导入 JWT 相关的两个包，分别是 jsonwebtoken 和 express-jwt</span>
<span class="token keyword">const</span> jwt <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'jsonwebtoken'</span><span class="token punctuation">)</span>
<span class="token keyword">const</span> expressJWT <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'express-jwt'</span><span class="token punctuation">)</span>

<span class="token comment">// 允许跨域资源共享</span>
<span class="token keyword">const</span> cors <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'cors'</span><span class="token punctuation">)</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span><span class="token function">cors</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>

<span class="token comment">// 托管静态页面</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>express<span class="token punctuation">.</span><span class="token function">static</span><span class="token punctuation">(</span><span class="token string">'./pages'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token comment">// 解析 POST 提交过来的表单数据</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>express<span class="token punctuation">.</span><span class="token function">urlencoded</span><span class="token punctuation">(</span><span class="token punctuation">{</span> extended<span class="token operator">:</span> <span class="token boolean">false</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">)</span>

<span class="token comment">// TODO_02：定义 secret 密钥，建议将密钥命名为 secretKey</span>
<span class="token keyword">const</span> secretKey <span class="token operator">=</span> <span class="token string">'itheima No1 ^_^'</span>

<span class="token comment">// TODO_04：注册将 JWT 字符串解析还原成 JSON 对象的中间件</span>
<span class="token comment">// 注意：只要配置成功了 express-jwt 这个中间件，就可以把解析出来的用户信息，挂载到 req.user 属性上</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span><span class="token function">expressJWT</span><span class="token punctuation">(</span><span class="token punctuation">{</span> secret<span class="token operator">:</span> secretKey <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">unless</span><span class="token punctuation">(</span><span class="token punctuation">{</span> path<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token regex">/^\/api\//</span><span class="token punctuation">]</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">)</span>

<span class="token comment">// 登录接口</span>
app<span class="token punctuation">.</span><span class="token function">post</span><span class="token punctuation">(</span><span class="token string">'/api/login'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token comment">// 将 req.body 请求体中的数据，转存为 userinfo 常量</span>
  <span class="token keyword">const</span> userinfo <span class="token operator">=</span> req<span class="token punctuation">.</span>body
  <span class="token comment">// 登录失败</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span>userinfo<span class="token punctuation">.</span>username <span class="token operator">!==</span> <span class="token string">'admin'</span> <span class="token operator">||</span> userinfo<span class="token punctuation">.</span>password <span class="token operator">!==</span> <span class="token string">'000000'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
      status<span class="token operator">:</span> <span class="token number">400</span><span class="token punctuation">,</span>
      message<span class="token operator">:</span> <span class="token string">'登录失败！'</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span>
  <span class="token comment">// 登录成功</span>
  <span class="token comment">// TODO_03：在登录成功之后，调用 jwt.sign() 方法生成 JWT 字符串。并通过 token 属性发送给客户端</span>
  <span class="token comment">// 参数1：用户的信息对象</span>
  <span class="token comment">// 参数2：加密的秘钥</span>
  <span class="token comment">// 参数3：配置对象，可以配置当前 token 的有效期</span>
  <span class="token comment">// 记住：千万不要把密码加密到 token 字符中</span>
  <span class="token keyword">const</span> tokenStr <span class="token operator">=</span> jwt<span class="token punctuation">.</span><span class="token function">sign</span><span class="token punctuation">(</span><span class="token punctuation">{</span> username<span class="token operator">:</span> userinfo<span class="token punctuation">.</span>username <span class="token punctuation">}</span><span class="token punctuation">,</span> secretKey<span class="token punctuation">,</span> <span class="token punctuation">{</span> expiresIn<span class="token operator">:</span> <span class="token string">'30s'</span> <span class="token punctuation">}</span><span class="token punctuation">)</span>
  res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
    status<span class="token operator">:</span> <span class="token number">200</span><span class="token punctuation">,</span>
    message<span class="token operator">:</span> <span class="token string">'登录成功！'</span><span class="token punctuation">,</span>
    token<span class="token operator">:</span> tokenStr<span class="token punctuation">,</span> <span class="token comment">// 要发送给客户端的 token 字符串</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

<span class="token comment">// 这是一个有权限的 API 接口</span>
app<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">'/admin/getinfo'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token comment">// TODO_05：使用 req.user 获取用户信息，并使用 data 属性将用户信息发送给客户端</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>req<span class="token punctuation">.</span>user<span class="token punctuation">)</span>
  res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
    status<span class="token operator">:</span> <span class="token number">200</span><span class="token punctuation">,</span>
    message<span class="token operator">:</span> <span class="token string">'获取用户信息成功！'</span><span class="token punctuation">,</span>
    data<span class="token operator">:</span> req<span class="token punctuation">.</span>user<span class="token punctuation">,</span> <span class="token comment">// 要发送给客户端的用户信息</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

<span class="token comment">// TODO_06：使用全局错误处理中间件，捕获解析 JWT 失败后产生的错误</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">err<span class="token punctuation">,</span> req<span class="token punctuation">,</span> res<span class="token punctuation">,</span> next</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token comment">// 这次错误是由 token 解析失败导致的</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span>err<span class="token punctuation">.</span>name <span class="token operator">===</span> <span class="token string">'UnauthorizedError'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
      status<span class="token operator">:</span> <span class="token number">401</span><span class="token punctuation">,</span>
      message<span class="token operator">:</span> <span class="token string">'无效的token'</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span>
  res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
    status<span class="token operator">:</span> <span class="token number">500</span><span class="token punctuation">,</span>
    message<span class="token operator">:</span> <span class="token string">'未知的错误'</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

<span class="token comment">// 调用 app.listen 方法，指定端口号并启动web服务器</span>
app<span class="token punctuation">.</span><span class="token function">listen</span><span class="token punctuation">(</span><span class="token number">80</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Express server running at http://127.0.0.1:80'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

</code></pre></div><h3 id="_6-项目初始化"><a href="#_6-项目初始化" class="header-anchor">#</a> 6. 项目初始化</h3> <h4 id="_6-1-项目概述"><a href="#_6-1-项目概述" class="header-anchor">#</a> 6.1  项目概述</h4> <ol><li><a href="http://www.escook.cn:8088/#/" target="_blank" rel="noopener noreferrer">在线笔记与文档<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></li> <li><a href="https://www.showdoc.cc/escook?page_id=3707158761215217" target="_blank" rel="noopener noreferrer">需要完成的大事件功能<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></li> <li>本地笔记与文档，在 <code>ppt</code> 文件夹中，<code>ev_api_server.pdf</code></li></ol> <h4 id="_6-2-创建项目"><a href="#_6-2-创建项目" class="header-anchor">#</a> 6.2 创建项目</h4> <ol><li>新建  <code>api_server</code> 文件夹作为项目根目录，并在项目根目录中运行如下的命令，初始化包管理配置文件</li></ol> <div class="language-js extra-class"><pre class="language-js"><code>npm init <span class="token operator">-</span>y
</code></pre></div><ol start="2"><li>运行如下的命令，安装特定版本的  <code>express</code></li></ol> <div class="language-js extra-class"><pre class="language-js"><code>npm i express@<span class="token number">4.17</span><span class="token number">.1</span>
</code></pre></div><ol start="3"><li>在项目根目录中新建  <code>app.js</code> 作为整个项目的入口文件，并初始化如下的代码</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 导入 express 模块</span>
<span class="token keyword">const</span> express <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'express'</span><span class="token punctuation">)</span>

<span class="token comment">// 创建 express 的服务器实例</span>
<span class="token keyword">const</span> app <span class="token operator">=</span> <span class="token function">express</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

<span class="token comment">// 在此处进行功能开发</span>

<span class="token comment">// 指定端口并启动 web 服务器</span>
app<span class="token punctuation">.</span><span class="token function">listen</span><span class="token punctuation">(</span><span class="token number">8000</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'api server running at http://127.0.0.1:8000'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

</code></pre></div><h4 id="_6-3-配置-cors-跨域和解析表单数据的中间件"><a href="#_6-3-配置-cors-跨域和解析表单数据的中间件" class="header-anchor">#</a> 6.3 配置 cors 跨域和解析表单数据的中间件</h4> <h5 id="_6-3-1-配置-cors-跨域"><a href="#_6-3-1-配置-cors-跨域" class="header-anchor">#</a> 6.3.1 配置 cors 跨域</h5> <ol><li>运行如下的命令，安装  <code>cors</code> 中间件</li></ol> <div class="language-js extra-class"><pre class="language-js"><code>cnpm i cors@<span class="token number">2.8</span><span class="token number">.5</span> <span class="token operator">--</span>save
</code></pre></div><ol start="2"><li>在  <code>app.js</code> 中导入并配置  <code>cors</code> 中间件</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 导入 express 模块</span>
<span class="token keyword">const</span> express <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'express'</span><span class="token punctuation">)</span>

<span class="token comment">// 创建 express 的服务器实例</span>
<span class="token keyword">const</span> app <span class="token operator">=</span> <span class="token function">express</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

<span class="token comment">// 导入 cors 中间件</span>
<span class="token keyword">const</span> cors <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'cors'</span><span class="token punctuation">)</span>
<span class="token comment">// 将 cors 注册为全局中间件</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>cors<span class="token punctuation">)</span>

<span class="token comment">// 指定端口并启动 web 服务器</span>
app<span class="token punctuation">.</span><span class="token function">listen</span><span class="token punctuation">(</span><span class="token number">8000</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'api server running at http://127.0.0.1:8000'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

</code></pre></div><h5 id="_6-3-2-配置解析表单数据的中间件"><a href="#_6-3-2-配置解析表单数据的中间件" class="header-anchor">#</a> 6.3.2 配置解析表单数据的中间件</h5> <ol><li>配置解析 <code>application/x-www-form-urlencoded</code> 格式的表单数据的中间件</li></ol> <div class="language-js extra-class"><pre class="language-js"><code>app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>express<span class="token punctuation">.</span><span class="token function">urlencoded</span><span class="token punctuation">(</span><span class="token punctuation">{</span> extended<span class="token operator">:</span> <span class="token boolean">false</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
</code></pre></div><ol start="2"><li>完整代码</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 导入 express 模块</span>
<span class="token keyword">const</span> express <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'express'</span><span class="token punctuation">)</span>

<span class="token comment">// 创建 express 的服务器实例</span>
<span class="token keyword">const</span> app <span class="token operator">=</span> <span class="token function">express</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

<span class="token comment">// 导入 cors 中间件</span>
<span class="token keyword">const</span> cors <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'cors'</span><span class="token punctuation">)</span>
<span class="token comment">// 将 cors 注册为全局中间件</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>cors<span class="token punctuation">)</span>

<span class="token comment">// 配置解析 application/x-www-form-urlencoded 格式的表单数据的中间件</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>express<span class="token punctuation">.</span><span class="token function">urlencoded</span><span class="token punctuation">(</span><span class="token punctuation">{</span> extended<span class="token operator">:</span> <span class="token boolean">false</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">)</span>

<span class="token comment">// 指定端口并启动 web 服务器</span>
app<span class="token punctuation">.</span><span class="token function">listen</span><span class="token punctuation">(</span><span class="token number">8000</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'api server running at http://127.0.0.1:8000'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

</code></pre></div><h4 id="_6-4-初始化路由相关的文件夹"><a href="#_6-4-初始化路由相关的文件夹" class="header-anchor">#</a> 6.4 初始化路由相关的文件夹</h4> <ol><li>在项目根目录中，新建  <code>router</code> 文件夹，用来存放所有的 路由 模块</li></ol> <ul><li>路由模块中，只存放客户端的请求与处理函数之间的映射关系</li></ul> <ol start="2"><li>在项目根目录中，新建  <code>router_handler</code> 文件夹，用来存放所有的  路由处理函数模块</li></ol> <ul><li>路由处理函数模块中，专门负责存放每个路由对应的处理函数</li></ul> <h4 id="_6-5-初始化用户路由模块"><a href="#_6-5-初始化用户路由模块" class="header-anchor">#</a> 6.5 初始化用户路由模块</h4> <ol><li>在 <code>router</code> 文件夹中，新建 <code>user.js</code> 文件，作为用户的路由模块</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// router --&gt; user.js</span>

<span class="token keyword">const</span> express <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'express'</span><span class="token punctuation">)</span>
<span class="token comment">// 创建路由对象</span>
<span class="token keyword">const</span> router <span class="token operator">=</span> express<span class="token punctuation">.</span><span class="token function">Router</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

<span class="token comment">// 注册新用户</span>
router<span class="token punctuation">.</span><span class="token function">post</span><span class="token punctuation">(</span><span class="token string">'/reguser'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token string">'reguser Ok'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

<span class="token comment">// 登录</span>
router<span class="token punctuation">.</span><span class="token function">post</span><span class="token punctuation">(</span><span class="token string">'/login'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token string">'Login Ok'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

<span class="token comment">// 将路由对象共享出去</span>
module<span class="token punctuation">.</span>exports <span class="token operator">=</span> router

</code></pre></div><ol start="2"><li>在  <code>app.js</code> 中，导入并使用  用户路由模块</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 导入 express 模块</span>
<span class="token keyword">const</span> express <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'express'</span><span class="token punctuation">)</span>

<span class="token comment">// 创建 express 的服务器实例</span>
<span class="token keyword">const</span> app <span class="token operator">=</span> <span class="token function">express</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

<span class="token comment">// 导入 cors 中间件</span>
<span class="token keyword">const</span> cors <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'cors'</span><span class="token punctuation">)</span>
<span class="token comment">// 将 cors 注册为全局中间件</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>cors<span class="token punctuation">)</span>

<span class="token comment">// 配置解析 application/x-www-form-urlencoded 格式的表单数据的中间件</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>express<span class="token punctuation">.</span><span class="token function">urlencoded</span><span class="token punctuation">(</span><span class="token punctuation">{</span> extended<span class="token operator">:</span> <span class="token boolean">false</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">)</span>

<span class="token comment">// 导入并注册用户路由模块</span>
<span class="token keyword">const</span> userRouter <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'./router/user'</span><span class="token punctuation">)</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span><span class="token string">'/api'</span><span class="token punctuation">,</span> userRouter<span class="token punctuation">)</span>

<span class="token comment">// 指定端口并启动 web 服务器</span>
app<span class="token punctuation">.</span><span class="token function">listen</span><span class="token punctuation">(</span><span class="token number">8000</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'api server running at http://127.0.0.1:8000'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

</code></pre></div><h4 id="_6-6-抽离用户路由模块中的处理函数"><a href="#_6-6-抽离用户路由模块中的处理函数" class="header-anchor">#</a> 6.6  抽离用户路由模块中的处理函数</h4> <blockquote><p>目的：为了保证  <strong>路由模块</strong> 的纯粹性，所有的  <strong>路由处理函数</strong> ，必须抽离到对应的  <strong>路由处理函数模块</strong> 中</p></blockquote> <ol><li>在  <code>/router_handler/user.js</code> 中，使用  <code>exports</code> 对象，分别向外共享如下两个路由处理函数</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">/**
 * 定义和用户相关的路由处理函数，功 /router/user.js 模块尽心调用
 */</span>

<span class="token comment">// 注册用户的处理函数</span>
exports<span class="token punctuation">.</span><span class="token function-variable function">regUser</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token string">'reguser Ok'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>

<span class="token comment">// 登录的处理函数</span>
exports<span class="token punctuation">.</span><span class="token function-variable function">login</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token string">'login Ok'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>

</code></pre></div><ol start="2"><li>将  <code>/router/user.js</code> 中的代码修改为如下结构</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">const</span> express <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'express'</span><span class="token punctuation">)</span>
<span class="token comment">// 创建路由对象</span>
<span class="token keyword">const</span> router <span class="token operator">=</span> express<span class="token punctuation">.</span><span class="token function">Router</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

<span class="token comment">// 导入用户路由处理函数模块</span>
<span class="token keyword">const</span> userHandle <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'../router_handler/user'</span><span class="token punctuation">)</span>

<span class="token comment">// 注册新用户</span>
router<span class="token punctuation">.</span><span class="token function">post</span><span class="token punctuation">(</span><span class="token string">'/reguser'</span><span class="token punctuation">,</span> userHandle<span class="token punctuation">.</span>regUser<span class="token punctuation">)</span>
<span class="token comment">// 登录功能</span>
router<span class="token punctuation">.</span><span class="token function">post</span><span class="token punctuation">(</span><span class="token string">'/login'</span><span class="token punctuation">,</span> userHandle<span class="token punctuation">.</span>login<span class="token punctuation">)</span>

<span class="token comment">// 将路由对象共享出去</span>
module<span class="token punctuation">.</span>exports <span class="token operator">=</span> router

</code></pre></div><h3 id="_7-注册新用户"><a href="#_7-注册新用户" class="header-anchor">#</a> 7.  注册新用户</h3> <h4 id="_7-1-创建用户表"><a href="#_7-1-创建用户表" class="header-anchor">#</a> 7.1 创建用户表</h4> <ol><li>在  <code>my_db_01</code> 数据库中，新建  <code>ev_users</code> 表</li></ol> <img src="/heima2020/assets/img/023 - 创建用户表.22c42645.png" style="zoom:80%;"> <h4 id="_7-2-安装配置-mysql-模块"><a href="#_7-2-安装配置-mysql-模块" class="header-anchor">#</a> 7.2 安装配置 mysql 模块</h4> <blockquote><p>在 API 接口项目中，需要安装并配置  mysql 这个第三方模块，来连接和操作 MySQL 数据库</p></blockquote> <ol><li>安装 <code>mysql</code> 模块</li></ol> <div class="language-js extra-class"><pre class="language-js"><code>npm i mysql@<span class="token number">2.18</span><span class="token number">.1</span>
</code></pre></div><ol start="2"><li>在项目根目录中新建  <code>/db/index.js</code> 文件，在此自定义模块中创建数据库的连接对象</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 导入 mysql 模块</span>
<span class="token keyword">const</span> mysql <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'mysql'</span><span class="token punctuation">)</span>

<span class="token comment">// 创建数据库连接对象</span>
<span class="token keyword">const</span> db <span class="token operator">=</span> mysql<span class="token punctuation">.</span><span class="token function">createPool</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  host<span class="token operator">:</span> <span class="token string">'127.0.0.1'</span><span class="token punctuation">,</span>
  user<span class="token operator">:</span> <span class="token string">'root'</span><span class="token punctuation">,</span>
  password<span class="token operator">:</span> <span class="token string">'admin123'</span><span class="token punctuation">,</span>
  database<span class="token operator">:</span> <span class="token string">'my_db_01'</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

<span class="token comment">// 向外共享 db 数据库连接对象</span>
module<span class="token punctuation">.</span>exports <span class="token operator">=</span> db

</code></pre></div><h4 id="_7-3-检测表单数据是否合法"><a href="#_7-3-检测表单数据是否合法" class="header-anchor">#</a> 7.3 检测表单数据是否合法</h4> <h5 id="_7-3-1-注册功能实现步骤"><a href="#_7-3-1-注册功能实现步骤" class="header-anchor">#</a> 7.3.1 注册功能实现步骤</h5> <ol><li>检测表单数据是否合法</li> <li>检测用户名是否被占用</li> <li>对密码进行加密处理</li> <li>插入新用户</li></ol> <h5 id="_7-3-2-检测表单数据是否合法"><a href="#_7-3-2-检测表单数据是否合法" class="header-anchor">#</a> 7.3.2 检测表单数据是否合法</h5> <ol><li>判断用户名和密码是否为空</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 注册用户的处理函数</span>
exports<span class="token punctuation">.</span><span class="token function-variable function">regUser</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token comment">// 获取到客户端提高到服务器的用户信息</span>
  <span class="token keyword">const</span> userinfo <span class="token operator">=</span> req<span class="token punctuation">.</span>body

  <span class="token comment">// 对表单中的数据进行合法性校验</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>userinfo<span class="token punctuation">.</span>username <span class="token operator">||</span> <span class="token operator">!</span>userinfo<span class="token punctuation">.</span>password<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token punctuation">{</span> status<span class="token operator">:</span> <span class="token number">1</span><span class="token punctuation">,</span> message<span class="token operator">:</span> <span class="token string">'用户名和密码不正确'</span> <span class="token punctuation">}</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span>
  
  res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token string">'reguser Ok'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
</code></pre></div><h4 id="_7-4-检测用户名是否合法"><a href="#_7-4-检测用户名是否合法" class="header-anchor">#</a> 7.4 检测用户名是否合法</h4> <ol><li>导入数据库操作模块</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 导入数据库操作模块</span>
<span class="token keyword">const</span> db <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'../db/index'</span><span class="token punctuation">)</span>
</code></pre></div><ol start="2"><li>定义 SQL 语句</li></ol> <div class="language-js extra-class"><pre class="language-js"><code>  <span class="token comment">// 定义 sql 语句</span>
  <span class="token keyword">const</span> sql <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">select * from ev_users where username=?</span><span class="token template-punctuation string">`</span></span>
</code></pre></div><ol start="3"><li>执行 SQL 语句并根据结果判断用户名是否被占用</li></ol> <div class="language-js extra-class"><pre class="language-js"><code>db<span class="token punctuation">.</span><span class="token function">query</span><span class="token punctuation">(</span>sql<span class="token punctuation">,</span> userinfo<span class="token punctuation">.</span>username<span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">err<span class="token punctuation">,</span> results</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token comment">// 执行 sql 语句失败</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>err<span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token keyword">return</span> res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token punctuation">{</span> status<span class="token operator">:</span> <span class="token number">1</span><span class="token punctuation">,</span> message<span class="token operator">:</span> err<span class="token punctuation">.</span>message <span class="token punctuation">}</span><span class="token punctuation">)</span>
    <span class="token punctuation">}</span>

    <span class="token comment">// 用户名被占用</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>results<span class="token punctuation">.</span>length <span class="token operator">&gt;</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token keyword">return</span> res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token punctuation">{</span> status<span class="token operator">:</span> <span class="token number">1</span><span class="token punctuation">,</span> message<span class="token operator">:</span> <span class="token string">'用户名被占用，请更换其他用户名'</span> <span class="token punctuation">}</span><span class="token punctuation">)</span>
    <span class="token punctuation">}</span>

    <span class="token comment">// 用户名可用，继续后续流程</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
</code></pre></div><ol start="4"><li>完整代码</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 导入数据库操作模块</span>
<span class="token keyword">const</span> db <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'../db/index'</span><span class="token punctuation">)</span>

<span class="token comment">// 注册用户的处理函数</span>
exports<span class="token punctuation">.</span><span class="token function-variable function">regUser</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token comment">// 获取到客户端提高到服务器的用户信息</span>
  <span class="token keyword">const</span> userinfo <span class="token operator">=</span> req<span class="token punctuation">.</span>body

  <span class="token comment">// 对表单中的数据进行合法性校验</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>userinfo<span class="token punctuation">.</span>username <span class="token operator">||</span> <span class="token operator">!</span>userinfo<span class="token punctuation">.</span>password<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token punctuation">{</span> status<span class="token operator">:</span> <span class="token number">1</span><span class="token punctuation">,</span> message<span class="token operator">:</span> <span class="token string">'用户名和密码不正确'</span> <span class="token punctuation">}</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span>

  <span class="token comment">// 定义 sql 语句</span>
  <span class="token keyword">const</span> sql <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">select * from ev_users where username=?</span><span class="token template-punctuation string">`</span></span>
  <span class="token comment">// 执行 sql 语句并根据结果判断用户名是否被占用</span>
  db<span class="token punctuation">.</span><span class="token function">query</span><span class="token punctuation">(</span>sql<span class="token punctuation">,</span> userinfo<span class="token punctuation">.</span>username<span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">err<span class="token punctuation">,</span> results</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token comment">// 执行 sql 语句失败</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>err<span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token keyword">return</span> res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token punctuation">{</span> status<span class="token operator">:</span> <span class="token number">1</span><span class="token punctuation">,</span> message<span class="token operator">:</span> err<span class="token punctuation">.</span>message <span class="token punctuation">}</span><span class="token punctuation">)</span>
    <span class="token punctuation">}</span>

    <span class="token comment">// 用户名被占用</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>results<span class="token punctuation">.</span>length <span class="token operator">&gt;</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token keyword">return</span> res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token punctuation">{</span> status<span class="token operator">:</span> <span class="token number">1</span><span class="token punctuation">,</span> message<span class="token operator">:</span> <span class="token string">'用户名被占用，请更换其他用户名'</span> <span class="token punctuation">}</span><span class="token punctuation">)</span>
    <span class="token punctuation">}</span>

    <span class="token comment">// 用户名可用，继续后续流程</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>

  res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token string">'reguser Ok'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
</code></pre></div><h4 id="_7-5-对密码进行加密处理"><a href="#_7-5-对密码进行加密处理" class="header-anchor">#</a> 7.5 对密码进行加密处理</h4> <h5 id="_7-5-1-什么需要对密码进行加密以及-bcryptjs-的优点"><a href="#_7-5-1-什么需要对密码进行加密以及-bcryptjs-的优点" class="header-anchor">#</a> 7.5.1 什么需要对密码进行加密以及 bcryptjs 的优点</h5> <ol><li>为了保证密码的安全性，不建议在数据库以  <strong>明文</strong> 的形式保存用户密码，推荐对密码进行 <strong>加密存储</strong></li> <li>在当前项目中，使用  <code>bcryptjs</code> 对用户密码进行加密，优点：</li></ol> <ul><li>加密之后的密码，无法被逆向破解</li> <li>同一明文密码多次加密，得到的加密结果各不相同，保证了安全性</li></ul> <h5 id="_7-5-2-使用-bcryptjs-对密码进行加密"><a href="#_7-5-2-使用-bcryptjs-对密码进行加密" class="header-anchor">#</a> 7.5.2 使用 bcryptjs 对密码进行加密</h5> <ol><li>安装指定版本的  <code>bcryptjs</code></li></ol> <div class="language-js extra-class"><pre class="language-js"><code>cnpm i bcryptjs@<span class="token number">2.4</span><span class="token number">.3</span> <span class="token operator">-</span><span class="token constant">S</span>
</code></pre></div><ol start="2"><li>在  <code>/router_handler/user.js</code> 中，导入  <code>bcryptjs</code></li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">const</span> bcrypt <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'bcryptjs'</span><span class="token punctuation">)</span>
</code></pre></div><ol start="3"><li>在注册用户的处理函数中，确认用户名可用之后，调用 <code>bcrypt.hashSync</code> (明文密码, 随机盐的长度) 方法，对用户的密码进行加密处理</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 注册用户的处理函数</span>
exports<span class="token punctuation">.</span><span class="token function-variable function">regUser</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  
   <span class="token comment">// coding……</span>
    
  db<span class="token punctuation">.</span><span class="token function">query</span><span class="token punctuation">(</span>sqlStr<span class="token punctuation">,</span> userinfo<span class="token punctuation">.</span>username<span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">err<span class="token punctuation">,</span> results</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token comment">// 执行 sql 语句失败</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>err<span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token keyword">return</span> res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token punctuation">{</span> status<span class="token operator">:</span> <span class="token number">1</span><span class="token punctuation">,</span> message<span class="token operator">:</span> err<span class="token punctuation">.</span>message <span class="token punctuation">}</span><span class="token punctuation">)</span>
    <span class="token punctuation">}</span>

    <span class="token comment">// 用户名被占用</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>results<span class="token punctuation">.</span>length <span class="token operator">&gt;</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token keyword">return</span> res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token punctuation">{</span> status<span class="token operator">:</span> <span class="token number">1</span><span class="token punctuation">,</span> message<span class="token operator">:</span> <span class="token string">'用户名被占用，请更换其他用户名'</span> <span class="token punctuation">}</span><span class="token punctuation">)</span>
    <span class="token punctuation">}</span>

    <span class="token comment">// 用户名可用，继续后续流程</span>
    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>userinfo<span class="token punctuation">)</span>
    <span class="token comment">// 对用户的密码，进行 bcrype 加密，返回值是加密以后的密码字符串</span>
    userinfo<span class="token punctuation">.</span>password <span class="token operator">=</span> bcrypt<span class="token punctuation">.</span><span class="token function">hashSync</span><span class="token punctuation">(</span>userinfo<span class="token punctuation">.</span>password<span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">)</span>
    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>userinfo<span class="token punctuation">)</span>
    res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token string">'reguser Ok'</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
</code></pre></div><h4 id="_7-6-插入新用户"><a href="#_7-6-插入新用户" class="header-anchor">#</a> 7.6 插入新用户</h4> <ol><li>定义插入用户的 <code>SQL</code> 语句</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">const</span> sql <span class="token operator">=</span> <span class="token string">'insert into ev_users set ?'</span>
</code></pre></div><ol start="2"><li>调用 <code>db.query()</code> 执行 <code>SQL</code> 语句，插入新用户</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 注册用户的处理函数</span>
exports<span class="token punctuation">.</span><span class="token function-variable function">regUser</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
   
  <span class="token comment">// coding…… </span>
    
  <span class="token comment">// 执行 sql 语句并根据结果判断用户名是否被占用</span>
  db<span class="token punctuation">.</span><span class="token function">query</span><span class="token punctuation">(</span>sqlStr<span class="token punctuation">,</span> userinfo<span class="token punctuation">.</span>username<span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">err<span class="token punctuation">,</span> results</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token comment">// 执行 sql 语句失败</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>err<span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token keyword">return</span> res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token punctuation">{</span> status<span class="token operator">:</span> <span class="token number">1</span><span class="token punctuation">,</span> message<span class="token operator">:</span> err<span class="token punctuation">.</span>message <span class="token punctuation">}</span><span class="token punctuation">)</span>
    <span class="token punctuation">}</span>

    <span class="token comment">// 用户名被占用</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>results<span class="token punctuation">.</span>length <span class="token operator">&gt;</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token keyword">return</span> res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token punctuation">{</span> status<span class="token operator">:</span> <span class="token number">1</span><span class="token punctuation">,</span> message<span class="token operator">:</span> <span class="token string">'用户名被占用，请更换其他用户名'</span> <span class="token punctuation">}</span><span class="token punctuation">)</span>
    <span class="token punctuation">}</span>

    <span class="token comment">// 用户名可用，继续后续流程</span>
    <span class="token comment">// 对用户的密码，进行 bcrype 加密，返回值是加密以后的密码字符串</span>
    userinfo<span class="token punctuation">.</span>password <span class="token operator">=</span> bcrypt<span class="token punctuation">.</span><span class="token function">hashSync</span><span class="token punctuation">(</span>userinfo<span class="token punctuation">.</span>password<span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">)</span>

    <span class="token comment">// 定义插入用户的 SQL 语句 </span>
    <span class="token keyword">const</span> sql <span class="token operator">=</span> <span class="token string">'insert into ev_users set ?'</span>

    <span class="token comment">// 调用 db.query() 执行 SQL 语句</span>
    db<span class="token punctuation">.</span><span class="token function">query</span><span class="token punctuation">(</span>sql<span class="token punctuation">,</span> <span class="token punctuation">{</span> username<span class="token operator">:</span> userinfo<span class="token punctuation">.</span>username<span class="token punctuation">,</span> password<span class="token operator">:</span> userinfo<span class="token punctuation">.</span>password <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">err<span class="token punctuation">,</span> results</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
      <span class="token comment">// 判断 sql 语句是否执行成功</span>
      <span class="token keyword">if</span> <span class="token punctuation">(</span>err<span class="token punctuation">)</span> <span class="token keyword">return</span> res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token punctuation">{</span> status<span class="token operator">:</span> <span class="token number">1</span><span class="token punctuation">,</span> message<span class="token operator">:</span> err<span class="token punctuation">.</span>message <span class="token punctuation">}</span><span class="token punctuation">)</span>
      <span class="token comment">// 判断影响行数是否为 1</span>
      <span class="token keyword">if</span> <span class="token punctuation">(</span>results<span class="token punctuation">.</span>affectedRows <span class="token operator">!==</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token keyword">return</span> res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token punctuation">{</span> status<span class="token operator">:</span> <span class="token number">1</span><span class="token punctuation">,</span> message<span class="token operator">:</span> <span class="token string">'注册用户失败，请稍后再试！'</span> <span class="token punctuation">}</span><span class="token punctuation">)</span>
      <span class="token comment">// 注册成功</span>
      res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token punctuation">{</span> status<span class="token operator">:</span> <span class="token number">0</span><span class="token punctuation">,</span> message<span class="token operator">:</span> <span class="token string">'注册成功'</span> <span class="token punctuation">}</span><span class="token punctuation">)</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
</code></pre></div><h3 id="_8-优化"><a href="#_8-优化" class="header-anchor">#</a> 8.  优化</h3> <h4 id="_8-1-优化-res-send-代码"><a href="#_8-1-优化-res-send-代码" class="header-anchor">#</a> 8.1  优化 res.send() 代码</h4> <blockquote><p>在处理函数中，需要多次调用 <strong>res.send()</strong> 向客户端响应  <strong>处理失败</strong> 的结果，为了简化代码，可以手动封装一个 res.cc() 函数</p></blockquote> <ol><li>在 <code>app.js</code>  中，所有路由之前，声明一个全局中间件，为 <code>res</code> 对象挂载一个 <code>res.cc()</code> 函数</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// coding……</span>

<span class="token comment">// 配置解析 application/x-www-form-urlencoded 格式的表单数据的中间件</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>express<span class="token punctuation">.</span><span class="token function">urlencoded</span><span class="token punctuation">(</span><span class="token punctuation">{</span> extended<span class="token operator">:</span> <span class="token boolean">false</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">)</span>

<span class="token comment">// 在所有路由之前，封装 res.cc 函数</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res<span class="token punctuation">,</span> next</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token comment">// status 的默认值为 1，表示失败的情况</span>
  <span class="token comment">// err 的值，可能是一个错误对象，也可能是一个错误的描述字符串</span>
  res<span class="token punctuation">.</span><span class="token function-variable function">cc</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">err<span class="token punctuation">,</span> status <span class="token operator">=</span> <span class="token number">1</span></span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
      status<span class="token punctuation">,</span>
      message<span class="token operator">:</span> err <span class="token keyword">instanceof</span> <span class="token class-name">Error</span> <span class="token operator">?</span> err<span class="token punctuation">.</span>message <span class="token operator">:</span> err
    <span class="token punctuation">}</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span>

  <span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

<span class="token comment">// 导入并注册用户路由模块</span>
<span class="token keyword">const</span> userRouter <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'./router/user'</span><span class="token punctuation">)</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span><span class="token string">'/api'</span><span class="token punctuation">,</span> userRouter<span class="token punctuation">)</span>

<span class="token comment">// coding……</span>
</code></pre></div><ol start="2"><li>将 <code>router_handle/user.js</code> 中的文件修改成 <code>res.cc</code> 的方式</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">/**
 * 定义和用户相关的路由处理函数，功 /router/user.js 模块尽心调用
 */</span>

<span class="token comment">// 导入数据库操作模块</span>
<span class="token keyword">const</span> db <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'../db/index'</span><span class="token punctuation">)</span>
<span class="token keyword">const</span> bcrypt <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'bcryptjs'</span><span class="token punctuation">)</span>

<span class="token comment">// 注册用户的处理函数</span>
exports<span class="token punctuation">.</span><span class="token function-variable function">regUser</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token comment">// 获取到客户端提高到服务器的用户信息</span>
  <span class="token keyword">const</span> userinfo <span class="token operator">=</span> req<span class="token punctuation">.</span>body
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>userinfo<span class="token punctuation">.</span>username<span class="token punctuation">)</span>

  <span class="token comment">// 对表单中的数据进行合法性校验</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>userinfo<span class="token punctuation">.</span>username <span class="token operator">||</span> <span class="token operator">!</span>userinfo<span class="token punctuation">.</span>password<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> res<span class="token punctuation">.</span><span class="token function">cc</span><span class="token punctuation">(</span><span class="token string">'用户名和密码不正确'</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span>

  <span class="token comment">// 定义 sql 语句</span>
  <span class="token keyword">const</span> sqlStr <span class="token operator">=</span> <span class="token string">'select * from ev_users where username=?'</span>
  <span class="token comment">// 执行 sql 语句并根据结果判断用户名是否被占用</span>
  db<span class="token punctuation">.</span><span class="token function">query</span><span class="token punctuation">(</span>sqlStr<span class="token punctuation">,</span> userinfo<span class="token punctuation">.</span>username<span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">err<span class="token punctuation">,</span> results</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token comment">// 执行 sql 语句失败</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>err<span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token keyword">return</span> res<span class="token punctuation">.</span><span class="token function">cc</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span>
    <span class="token punctuation">}</span>

    <span class="token comment">// 用户名被占用</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>results<span class="token punctuation">.</span>length <span class="token operator">&gt;</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token keyword">return</span> res<span class="token punctuation">.</span><span class="token function">cc</span><span class="token punctuation">(</span><span class="token string">'用户名被占用，请更换其他用户名'</span><span class="token punctuation">)</span>
    <span class="token punctuation">}</span>

    <span class="token comment">// 用户名可用，继续后续流程</span>
    <span class="token comment">// 对用户的密码，进行 bcrype 加密，返回值是加密以后的密码字符串</span>
    userinfo<span class="token punctuation">.</span>password <span class="token operator">=</span> bcrypt<span class="token punctuation">.</span><span class="token function">hashSync</span><span class="token punctuation">(</span>userinfo<span class="token punctuation">.</span>password<span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">)</span>

    <span class="token comment">// 定义插入用户的 SQL 语句 </span>
    <span class="token keyword">const</span> sql <span class="token operator">=</span> <span class="token string">'insert into ev_users set ?'</span>

    <span class="token comment">// 调用 db.query() 执行 SQL 语句</span>
    db<span class="token punctuation">.</span><span class="token function">query</span><span class="token punctuation">(</span>sql<span class="token punctuation">,</span> <span class="token punctuation">{</span> username<span class="token operator">:</span> userinfo<span class="token punctuation">.</span>username<span class="token punctuation">,</span> password<span class="token operator">:</span> userinfo<span class="token punctuation">.</span>password <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">err<span class="token punctuation">,</span> results</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
      <span class="token comment">// 判断 sql 语句是否执行成功</span>
      <span class="token keyword">if</span> <span class="token punctuation">(</span>err<span class="token punctuation">)</span> <span class="token keyword">return</span> res<span class="token punctuation">.</span><span class="token function">cc</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span>
      <span class="token comment">// 判断影响行数是否为 1</span>
      <span class="token keyword">if</span> <span class="token punctuation">(</span>results<span class="token punctuation">.</span>affectedRows <span class="token operator">!==</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token keyword">return</span> res<span class="token punctuation">.</span><span class="token function">cc</span><span class="token punctuation">(</span><span class="token string">'注册用户失败，请稍后再试！'</span><span class="token punctuation">)</span>
      <span class="token comment">// 注册成功</span>
      res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token punctuation">{</span> status<span class="token operator">:</span> <span class="token number">0</span><span class="token punctuation">,</span> message<span class="token operator">:</span> <span class="token string">'注册成功'</span> <span class="token punctuation">}</span><span class="token punctuation">)</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>

<span class="token comment">// 登录的处理函数</span>
exports<span class="token punctuation">.</span><span class="token function-variable function">login</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token string">'login Ok'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>

</code></pre></div><h4 id="_8-2-了解数据验证的原则"><a href="#_8-2-了解数据验证的原则" class="header-anchor">#</a> 8.2  了解数据验证的原则</h4> <blockquote><p>表单验证的原则：前端验证为辅，后端验证为主，后端永远不要相信前端提交过来的任何内容</p></blockquote> <ol><li>在实际开发中，前后端都需要对表单的数据进行合法性的验证，而且，<strong>后端做为数据合法性校验的最后一个关口</strong>，在拦截非法数据方面，起到了至关重要的作用</li> <li>单纯的使用  <code>if...else...</code> 的形式对数据合法性进行验证，效率低下、出错率高、维护性差。因此，
推荐使用第三方数据验证模块，来降低出错率、提高验证的效率与可维护性，让后端程序员把更多的精
力放在核心业务逻辑的处理上</li></ol> <h4 id="_8-3-介绍如何定义验证规则对象"><a href="#_8-3-介绍如何定义验证规则对象" class="header-anchor">#</a> 8.3 介绍如何定义验证规则对象</h4> <ol><li>安装 <code>@hapi/joi</code> 包，为表单中携带的每个数据项，定义验证规则</li></ol> <div class="language-js extra-class"><pre class="language-js"><code>cnpm install @hapi<span class="token operator">/</span>joi@<span class="token number">17.1</span><span class="token number">.0</span> <span class="token operator">-</span><span class="token constant">S</span>
</code></pre></div><ol start="2"><li>安装 <code>@escook/express-joi</code> 中间件，来实现自动对表单数据进行验证的功能</li></ol> <div class="language-js extra-class"><pre class="language-js"><code>cnpm i @escook<span class="token operator">/</span>express<span class="token operator">-</span>joi <span class="token operator">-</span><span class="token constant">S</span>
</code></pre></div><ol start="3"><li>相关验证规则的含义</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">/**
* string() 值必须是字符串
* alphanum() 值只能是包含 a-zA-Z0-9 的字符串
* min(length) 最小长度
* max(length) 最大长度
* required() 值是必填项，不能为 undefined
* pattern(正则表达式) 值必须符合正则表达式的规则
*/</span>

<span class="token keyword">var</span> getUsersSchema <span class="token operator">=</span> <span class="token punctuation">{</span>
  limit<span class="token operator">:</span> expressJoi<span class="token punctuation">.</span>Joi<span class="token punctuation">.</span>types<span class="token punctuation">.</span><span class="token function">Number</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">integer</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">min</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">max</span><span class="token punctuation">(</span><span class="token number">25</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
  offset<span class="token operator">:</span> expressJoi<span class="token punctuation">.</span>Joi<span class="token punctuation">.</span>types<span class="token punctuation">.</span><span class="token function">Number</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">integer</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">min</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">max</span><span class="token punctuation">(</span><span class="token number">25</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
  name<span class="token operator">:</span> expressJoi<span class="token punctuation">.</span>Joi<span class="token punctuation">.</span>types<span class="token punctuation">.</span><span class="token function">String</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">alphanum</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">min</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">max</span><span class="token punctuation">(</span><span class="token number">25</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
</code></pre></div><h4 id="_8-4-了解如何使用数验证的中间件"><a href="#_8-4-了解如何使用数验证的中间件" class="header-anchor">#</a> 8.4 了解如何使用数验证的中间件</h4> <ol><li>在路由中使用局部中间件</li> <li>在局部中间件中通过 <code>expressJoi(userSchema)</code>  的方式调用中间件进行参数验证</li> <li>验证通过以后，将结果转交给后面的回调函数</li> <li>验证失败以后，就会报一个全局的错误，只需要在错误级别中间件捕获错误，然后做下一步处理</li></ol> <h4 id="_8-5-定义验证规则模块"><a href="#_8-5-定义验证规则模块" class="header-anchor">#</a> 8.5 定义验证规则模块</h4> <ol><li>新建  <code>/schema/user.js</code> 用户信息验证规则模块，并初始化代码</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">const</span> joi <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'@hapi/joi'</span><span class="token punctuation">)</span>

<span class="token comment">/**
* string() 值必须是字符串
* alphanum() 值只能是包含 a-zA-Z0-9 的字符串
* min(length) 最小长度
* max(length) 最大长度
* required() 值是必填项，不能为 undefined
* pattern(正则表达式) 值必须符合正则表达式的规则
*/</span>

<span class="token comment">// 验证用户名、密码的规则</span>
<span class="token keyword">const</span> username <span class="token operator">=</span> joi<span class="token punctuation">.</span><span class="token function">string</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">alphanum</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">min</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">max</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">required</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token keyword">const</span> passoword <span class="token operator">=</span> joi<span class="token punctuation">.</span><span class="token function">string</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">pattern</span><span class="token punctuation">(</span><span class="token regex">/^[\S]{6, 12}$/</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">required</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

<span class="token comment">// 登录和注册表单的验证规则对象</span>
exports<span class="token punctuation">.</span>reg_login_schema <span class="token operator">=</span> <span class="token punctuation">{</span>
  <span class="token comment">// 表示需要对 req.body 中的数据进行验证</span>
  body<span class="token operator">:</span> <span class="token punctuation">{</span>
    username<span class="token punctuation">,</span>
    passoword
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

</code></pre></div><h4 id="_8-6-实现对表单数据验证方式的改造"><a href="#_8-6-实现对表单数据验证方式的改造" class="header-anchor">#</a> 8.6 实现对表单数据验证方式的改造</h4> <ol><li>将原始的 <code>if</code> 验证方式注释</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 对表单中的数据进行合法性校验</span>
<span class="token comment">// if (!userinfo.username || !userinfo.password) {</span>
<span class="token comment">//   // return res.send({ status: 1, message: '用户名和密码不正确' })</span>
<span class="token comment">//   return res.cc('用户名和密码不正确')</span>
<span class="token comment">// }</span>

</code></pre></div><ol start="2"><li>在 <code>router.js</code> 中导入验证数据的中间件以及验证规则对象，在需要验证的路由中使用局部中间件添加校验规则</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">const</span> express <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'express'</span><span class="token punctuation">)</span>
<span class="token comment">// 创建路由对象</span>
<span class="token keyword">const</span> router <span class="token operator">=</span> express<span class="token punctuation">.</span><span class="token function">Router</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

<span class="token comment">// 导入用户路由处理函数模块</span>
<span class="token keyword">const</span> userHandle <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'../router_handler/user'</span><span class="token punctuation">)</span>

<span class="token comment">// 1. 导入验证表单数据的中间件</span>
<span class="token keyword">const</span> expressJoi <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'@escook/express-joi'</span><span class="token punctuation">)</span>
<span class="token comment">// 2. 导入需要的验证规则对象</span>
<span class="token keyword">const</span> <span class="token punctuation">{</span> reg_login_schema <span class="token punctuation">}</span> <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'../schema/user'</span><span class="token punctuation">)</span>

<span class="token comment">// 注册新用户</span>
router<span class="token punctuation">.</span><span class="token function">post</span><span class="token punctuation">(</span><span class="token string">'/reguser'</span><span class="token punctuation">,</span> <span class="token function">expressJoi</span><span class="token punctuation">(</span>reg_login_schema<span class="token punctuation">)</span><span class="token punctuation">,</span> userHandle<span class="token punctuation">.</span>regUser<span class="token punctuation">)</span>
<span class="token comment">// 登录功能</span>
router<span class="token punctuation">.</span><span class="token function">post</span><span class="token punctuation">(</span><span class="token string">'/login'</span><span class="token punctuation">,</span> userHandle<span class="token punctuation">.</span>login<span class="token punctuation">)</span>

<span class="token comment">// 将路由对象共享出去</span>
module<span class="token punctuation">.</span>exports <span class="token operator">=</span> router

</code></pre></div><ol start="3"><li>验证可能会失败，所以在全局进行捕获</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 错误中间件</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">err<span class="token punctuation">,</span> req<span class="token punctuation">,</span> res<span class="token punctuation">,</span> next</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token comment">// 数据验证失败</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span>err <span class="token keyword">instanceof</span> <span class="token class-name">joi<span class="token punctuation">.</span>ValidationError</span><span class="token punctuation">)</span> <span class="token keyword">return</span> res<span class="token punctuation">.</span><span class="token function">cc</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span>
  <span class="token comment">// 未知错误</span>
  res<span class="token punctuation">.</span><span class="token function">cc</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

</code></pre></div></div> <footer class="page-edit"><!----> <!----></footer> <div class="page-nav"><p class="inner"><span class="prev">
      ←
      <a href="/heima2020/node/day05.html" class="prev">
        Node 第 5 天
      </a></span> <span class="next"><a href="/heima2020/node/day07.html">
        Node 第 7 天
      </a>
      →
    </span></p></div> </main></div><div class="global-ui"><!----></div></div>
    <script src="/heima2020/assets/js/app.e2adc9d2.js" defer></script><script src="/heima2020/assets/js/2.7389c9d3.js" defer></script><script src="/heima2020/assets/js/7.f611fe3c.js" defer></script>
  </body>
</html>
